vxcontrol/pentagi · warning
Token.InvalidRequest
Token.InvalidRequest
Error message
token with this name already exists
What it means
CreateToken enforces per-user uniqueness of active token names: before generating a token it queries for an existing non-deleted token with the same user_id and name, and if one exists it returns Token.InvalidRequest with 'token with this name already exists'. Names are only unique per user, not globally.
Source
Thrown at backend/pkg/server/services/api_tokens.go:89
logger.FromContext(c).WithError(err).Errorf("error binding JSON")
response.Error(c, response.ErrTokenInvalidRequest, err)
return
}
if err := req.Valid(); err != nil {
logger.FromContext(c).WithError(err).Errorf("error validating JSON")
response.Error(c, response.ErrTokenInvalidRequest, err)
return
}
if req.Name != nil && *req.Name != "" {
var existing models.APIToken
err := s.db.
Where("user_id = ? AND name = ? AND deleted_at IS NULL", uid, *req.Name).
First(&existing).
Error
if err == nil {
logger.FromContext(c).Errorf("token with name '%s' already exists for user %d", *req.Name, uid)
response.Error(c, response.ErrTokenInvalidRequest, errors.New("token with this name already exists"))
return
}
}
tokenID, err := auth.GenerateTokenID()
if err != nil {
logger.FromContext(c).WithError(err).Errorf("error generating token ID")
response.Error(c, response.ErrInternal, err)
return
}
claims := auth.MakeAPITokenClaims(tokenID, uhash, uid, rid, req.TTL)
token, err := auth.MakeAPIToken(s.globalSalt, claims)
if err != nil {
logger.FromContext(c).WithError(err).Errorf("error signing token")
response.Error(c, response.ErrInternal, err)
returnView on GitHub (pinned to ea665308ba)
Solutions
- Choose a different, unique name for the new token.
- List existing tokens (GET /tokens) and reuse or rename the existing one instead of creating a duplicate.
- Soft-delete the old token with the same name (DELETE /tokens/{id}) then re-create it.
- Make the creating script idempotent: look up the token by name first and reuse it on 409/invalid-request.
Example fix
// before
POST /tokens {"name":"ci-deploy"} // duplicate -> error
// after
POST /tokens {"name":"ci-deploy-2026-09"} // unique name succeeds Defensive patterns
Strategy: validation
Validate before calling
const names = (await api.get('/tokens')).data.tokens.map(t => t.name).filter(Boolean);
if (names.includes(desiredName)) throw new Error(`token name '${desiredName}' already in use`); Type guard
function isNameFree(name, existing) { return !existing.some(t => t.name === name); } Try / catch
try { await api.post('/tokens', { name }); }
catch (e) {
if (e.response?.data?.code === 'Token.InvalidRequest' && /already exists/.test(e.response.data.message)) {
name = `${name}-${Date.now()}`; // retry with unique suffix
} else throw e;
} Prevention
- Check existing token names before creating.
- Generate names with timestamps or UUIDs in automation.
- Debounce/disable the create button after first submit to avoid double-POSTs.
- Remember uniqueness is per-user and ignores soft-deleted tokens.
When it happens
Trigger: POST /tokens with a body {"name": "X"} when the same user already owns an active (not soft-deleted) token named X.
Common situations: Re-running an automation script that creates tokens idempotently by name; UI double-submit; user forgot an existing token with the same label; retry after a partial failure where the first creation actually succeeded.
Related errors
- invalid TokenStatus: %s
- %w: resource %q already exists and is not a directory
- Internal
- Agentlogs.InvalidRequest
- Token.CreationDisabled
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/42745a314b37a555.
Report an issue: GitHub.