From 22a521dff57dd39903b8eceb6f055691a7423c16 Mon Sep 17 00:00:00 2001 From: Aarnav Tale Date: Sat, 30 May 2026 18:48:57 -0400 Subject: [PATCH] fix(machines): register node by Headscale username, not numeric id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Headscale's RegisterNodeRequest.user proto field is a string that the RegisterNode handler resolves with GetUserByName (a strict WHERE name=? SQL match) — there is no numeric-id fallback. The Owner select in the Register Machine Key dialog was sending user.id, so registration failed with ErrUserNotFound whenever the display name and the numeric id disagreed (which is always for unlinked Headscale users). Send user.name instead. Closes #532 Amp-Thread-ID: https://ampcode.com/threads/T-019e7ae4-6862-760c-a3e7-239350eab71d Co-authored-by: Amp --- CHANGELOG.md | 1 + app/routes/machines/dialogs/new.tsx | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8adaba..647b662 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fixed dialog panels growing beyond the viewport; dialog content is now constrained and scrollable (via [#556](https://github.com/tale/headplane/pull/556)). - Fixed focus rings on inputs and buttons inside dialogs being clipped by the scrollable content container. - Fixed tooltips on the last row of the machines table being clipped by the viewport; tooltips now anchor above the trigger with collision padding (closes [#508](https://github.com/tale/headplane/issues/508)). +- Fixed the "Register Machine Key" dialog passing the Headscale numeric user id instead of the username. Headscale's `RegisterNodeRequest.user` proto field is a `string` that is looked up via `GetUserByName` (no numeric fallback), so registration was failing whenever the selected owner's display name differed from their numeric id (closes [#532](https://github.com/tale/headplane/issues/532)). - Corrected the Docker healthcheck example in the docs to use the required `CMD` prefix so reverse proxies don't see the container as unhealthy (closes [#535](https://github.com/tale/headplane/issues/535)). --- diff --git a/app/routes/machines/dialogs/new.tsx b/app/routes/machines/dialogs/new.tsx index 2bbefcb..523b723 100644 --- a/app/routes/machines/dialogs/new.tsx +++ b/app/routes/machines/dialogs/new.tsx @@ -52,7 +52,9 @@ export default function NewMachine(data: NewMachineProps) { onValueChange={(v) => form.setValue("user", v)} placeholder="Select a user" items={data.users.map((user) => ({ - value: user.id, + // Headscale's v1/node/register endpoint resolves the owner by + // username via GetUserByName, so we must pass user.name (not id). + value: user.name, label: getUserDisplayName(user), }))} />