[Bug] Node registration via the api fails despite having valid args #1090

Closed
opened 2025-12-29 02:28:13 +01:00 by adam · 3 comments
Owner

Originally created by @hss-wodom on GitHub (Aug 27, 2025).

Is this a support request?

  • This is not a support request

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I'm working on a tool to help me manage my tailscale nodes and the /api/v1/node/register endpoint isn't working as expected. I found a previous recent issue that looks identical to what I'm seeing, but the author closed it without comment. Given that they said that the registration succeeded via the container command (which I assume means the CLI), I think they probably didn't resolve the issue but simply no longer needed the API to work.

When I submit a request to the API route above on my headscale instance I get this error response:

{
    "code": 2,
    "message": "registration ID must be 24 characters long",
    "details": []
}

I was verified that key I passed in the request body was exactly 24 characters by hand, and it also passed the validation regex in my tool:

r"^[a-zA-Z0-9_-]{24}$"

Finally, I too was able to complete this test registration via the CLI. However, in my case I do still need the API since I'll need to register more nodes in the future. Other endpoints I tried such as listing and creating users have worked as expected. Is there an issue with the node registration API, or is the /swagger API documentation incorrect in some way? It's also possible that I'm making some slight mistake in my API call, but I've tried and retried it with every slight variation I can think of and given that all my calls to other endpoints have worked exactly as expected so far I think I'm formatting things correctly.

Expected Behavior

I expected the node to be registered to the specified user per the swagger API docs.

Steps To Reproduce

  1. Make an HTTP POST request to the api route mentioned above, complete with the appropriate auth header and body as specified in the swagger docs.

Environment

- OS: Ubuntu 24.04
- Headscale version: 0.26.0
- Tailscale version: 1.86.2

Runtime environment

  • Headscale is behind a (reverse) proxy
  • Headscale runs in a container

Debug information

I'd rather not publicly post the full logs listed above for privacy reasons, but if they are absolutely required I can send them via a more private method if one is available.

Originally created by @hss-wodom on GitHub (Aug 27, 2025). ### Is this a support request? - [x] This is not a support request ### Is there an existing issue for this? - [x] I have searched the existing issues ### Current Behavior I'm working on a tool to help me manage my tailscale nodes and the `/api/v1/node/register` endpoint isn't working as expected. I found [a previous recent issue](https://github.com/juanfont/headscale/issues/2710) that looks identical to what I'm seeing, but the author closed it without comment. Given that they said that the registration succeeded via the container command (which I assume means the CLI), I think they probably didn't resolve the issue but simply no longer needed the API to work. When I submit a request to the API route above on my headscale instance I get this error response: ```json { "code": 2, "message": "registration ID must be 24 characters long", "details": [] } ``` I was verified that key I passed in the request body was exactly 24 characters by hand, and it also passed the validation regex in my tool: ```python r"^[a-zA-Z0-9_-]{24}$" ``` Finally, I too was able to complete this test registration via the CLI. However, in my case I do still need the API since I'll need to register more nodes in the future. Other endpoints I tried such as listing and creating users have worked as expected. Is there an issue with the node registration API, or is the `/swagger` API documentation incorrect in some way? It's also possible that I'm making some slight mistake in my API call, but I've tried and retried it with every slight variation I can think of and given that all my calls to other endpoints have worked exactly as expected so far I think I'm formatting things correctly. ### Expected Behavior I expected the node to be registered to the specified user per the swagger API docs. ### Steps To Reproduce 1. Make an HTTP POST request to the api route mentioned above, complete with the appropriate auth header and body as specified in the swagger docs. ### Environment ```markdown - OS: Ubuntu 24.04 - Headscale version: 0.26.0 - Tailscale version: 1.86.2 ``` ### Runtime environment - [x] Headscale is behind a (reverse) proxy - [ ] Headscale runs in a container ### Debug information I'd rather not publicly post the full logs listed above for privacy reasons, but if they are absolutely required I can send them via a more private method if one is available.
adam added the bug label 2025-12-29 02:28:13 +01:00
adam closed this issue 2025-12-29 02:28:13 +01:00
Author
Owner

@gm852 commented on GitHub (Oct 1, 2025):

i can confirm this this for version 0.26 also

No matter how many chars you enter or how you try to send the request you get the same response.

POST {{server_host}}/api/v1/node/register
with json body

{
    "user": <userID>,
    "registration_id": "<token>"
}

returns

{
    "code": 2,
    "message": "registration ID must be 24 characters long",
    "details": []
}

Id really like to see a answer on this as in the code it asks for user and key values both as strings in /proto/headscale/v1/node.proto line 56 and the endpoint is for sure {{server_host}}/api/v1/node/register per proto/headscale/v1/headscale.proto line 96 but im also not a go dev.

logs claim the incoming info is empty. The Registering node registration_id= user= is not edited, thats how the server says it gets it.

2025-10-01T23:34:27+03:00 TRC finished writing mapresp to node mkey=mkey:d1e60ef00b1a7e7a2f13a4286c178a0cd642ac6b11278asdasacdasdadsasd3 node=DESKTOP-I1RU28Q timeSpent=0.491635
2025-10-01T23:34:27+03:00 TRC ../home/runner/work/headscale/headscale/hscontrol/poll.go:612 > update sent node=DESKTOP-I1RU28Q node.id=14 omitPeers=false readOnly=false stream=true
2025-10-01T23:34:32+03:00 TRC ../home/runner/work/headscale/headscale/hscontrol/app.go:387 > HTTP authentication invoked client_address=123.123.123.123:58601
2025-10-01T23:34:32+03:00 TRC Registering node registration_id= user=

in addition its worth noting i got logs to show a response after using this curl command
curl -v -H "Authorization: Bearer <token>" -d "user=6" -d "key=key" https://<server>/api/v1/node/register

  • OS: Ubuntu 22.04.5 LTS
  • Headscale version: 0.26.0
  • Tailscale version: 1.88.1
@gm852 commented on GitHub (Oct 1, 2025): i can confirm this this for version 0.26 also No matter how many chars you enter or how you try to send the request you get the same response. `POST {{server_host}}/api/v1/node/register` with json body ``` { "user": <userID>, "registration_id": "<token>" } ``` returns ``` { "code": 2, "message": "registration ID must be 24 characters long", "details": [] } ``` Id really like to see a answer on this as in the code it asks for user and key values both as strings in `/proto/headscale/v1/node.proto line 56` and the endpoint is for sure `{{server_host}}/api/v1/node/register` per `proto/headscale/v1/headscale.proto line 96` but im also not a go dev. logs claim the incoming info is empty. The `Registering node registration_id= user=` is not edited, thats how the server says it gets it. ``` 2025-10-01T23:34:27+03:00 TRC finished writing mapresp to node mkey=mkey:d1e60ef00b1a7e7a2f13a4286c178a0cd642ac6b11278asdasacdasdadsasd3 node=DESKTOP-I1RU28Q timeSpent=0.491635 2025-10-01T23:34:27+03:00 TRC ../home/runner/work/headscale/headscale/hscontrol/poll.go:612 > update sent node=DESKTOP-I1RU28Q node.id=14 omitPeers=false readOnly=false stream=true 2025-10-01T23:34:32+03:00 TRC ../home/runner/work/headscale/headscale/hscontrol/app.go:387 > HTTP authentication invoked client_address=123.123.123.123:58601 2025-10-01T23:34:32+03:00 TRC Registering node registration_id= user= ``` in addition its worth noting i got logs to show a response after using this curl command `curl -v -H "Authorization: Bearer <token>" -d "user=6" -d "key=key" https://<server>/api/v1/node/register` - OS: Ubuntu 22.04.5 LTS - Headscale version: 0.26.0 - Tailscale version: 1.88.1
Author
Owner

@gm852 commented on GitHub (Oct 1, 2025):

@hss-wodom try using curl or postman send the data as x-www-form-urlencoded and it should work.

also for some reason using query params works too so you could also just do
/api/v1/node/register?user=user&key=key

Image
@gm852 commented on GitHub (Oct 1, 2025): @hss-wodom try using curl or postman send the data as `x-www-form-urlencoded` and it should work. also for some reason using query params works too so you could also just do `/api/v1/node/register?user=user&key=key` <img width="1148" height="766" alt="Image" src="https://github.com/user-attachments/assets/6715fff3-a866-482b-95a6-8d11dc769eab" />
Author
Owner

@nblock commented on GitHub (Oct 19, 2025):

As noted by @gm852: send data as x-www-form-urlencoded, e.g. via: curl -H "Authorization: Bearer $API" -d user=$USER -d key=$KEY https://headscale.example.com/api/v1/node/register

@nblock commented on GitHub (Oct 19, 2025): As noted by @gm852: send data as `x-www-form-urlencoded`, e.g. via: `curl -H "Authorization: Bearer $API" -d user=$USER -d key=$KEY https://headscale.example.com/api/v1/node/register`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#1090