netbirdio/netbird · warning
tokenID is required
Error message
tokenID is required
What it means
Client-side guard in ReverseProxyTokensAPI.Delete against an empty proxy token ID. An empty ID would make url.PathEscape("") collapse the DELETE URL onto the collection endpoint /api/reverse-proxies/proxy-tokens, deleting nothing or hitting the wrong route. The guard rejects the call before any request is issued.
Source
Thrown at shared/management/client/rest/reverse_proxy_tokens.go:69
defer resp.Body.Close()
}
ret, err := parseResponse[api.ProxyTokenCreated](resp)
if err != nil {
return nil, err
}
return &ret, nil
}
// Delete revokes a previously-issued proxy token by ID. Revoked tokens
// remain in List output (with revoked=true) so operators can audit which
// credentials existed; the plain secret can no longer authenticate any
// new proxy registration.
func (a *ReverseProxyTokensAPI) Delete(ctx context.Context, tokenID string) error {
// Guard against the empty input: url.PathEscape("") returns "" which
// would collapse the request URL onto the collection endpoint and
// silently delete nothing (or 405 depending on routing).
if tokenID == "" {
return errors.New("tokenID is required")
}
resp, err := a.c.NewRequest(ctx, "DELETE", "/api/reverse-proxies/proxy-tokens/"+url.PathEscape(tokenID), nil, nil)
if err != nil {
return err
}
if resp.Body != nil {
defer resp.Body.Close()
}
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Use the token ID exactly as returned by the Create/List endpoints
- Validate the ID is non-empty before invoking Delete
- Log and skip empty IDs when iterating a list of tokens to revoke
Example fix
// before
err := restClient.ReverseProxyTokens.Delete(ctx, tokenID)
// after
if tokenID == "" {
return fmt.Errorf("tokenID is required to revoke a proxy token")
}
err := restClient.ReverseProxyTokens.Delete(ctx, tokenID) Defensive patterns
Strategy: validation
Validate before calling
if tokenID == "" {
return fmt.Errorf("tokenID is required before revoking a proxy token")
}
err := restClient.ReverseProxyTokens.Delete(ctx, tokenID) Try / catch
if err := restClient.ReverseProxyTokens.Delete(ctx, tokenID); err != nil {
if err.Error() == "tokenID is required" {
// the ID lookup upstream produced nothing; fix the source of tokenID
}
return err
} Prevention
- Capture the ID from the Create response and persist it
- Skip empty IDs when iterating lists of tokens to revoke
- Validate identifiers at config load time
When it happens
Trigger: Calling Delete(ctx, "") with a token ID variable that was never populated, e.g. an unset env var, a zero-value struct field, or a lookup that returned no ID.
Common situations: Revocation scripts iterating tokens parsed from stale output; config keys for the token ID omitted; copy-paste helper calls missing the argument.
Related errors
- clusterAddress is required
- service name is required
- service name exceeds maximum length of 255 characters
- at least one target is required
- private services require at least one access group
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/235a8c181f68857f.
Report an issue: GitHub.