{"record":{"id":"57d26ec7aa18093c","repo":"hashicorp/nomad","slug":"no-acl-token-returned","errorCode":null,"errorMessage":"no ACL token returned","messagePattern":"no ACL token returned","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/acl.go","lineNumber":237,"sourceCode":"\tif resp == nil {\n\t\treturn nil, nil, errors.New(\"no one-time token returned\")\n\t}\n\treturn resp.OneTimeToken, wm, nil\n}\n\n// ExchangeOneTimeToken is used to create a one-time token\nfunc (a *ACLTokens) ExchangeOneTimeToken(secret string, q *WriteOptions) (*ACLToken, *WriteMeta, error) {\n\tif secret == \"\" {\n\t\treturn nil, nil, errors.New(\"missing secret ID\")\n\t}\n\treq := &OneTimeTokenExchangeRequest{OneTimeSecretID: secret}\n\tvar resp *OneTimeTokenExchangeResponse\n\twm, err := a.client.put(\"/v1/acl/token/onetime/exchange\", req, &resp, q)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif resp == nil {\n\t\treturn nil, nil, errors.New(\"no ACL token returned\")\n\t}\n\treturn resp.Token, wm, nil\n}\n\nvar (\n\t// errMissingACLRoleID is the generic errors to use when a call is missing\n\t// the required ACL Role ID parameter.\n\terrMissingACLRoleID = errors.New(\"missing ACL role ID\")\n\n\t// errMissingACLAuthMethodName is the generic error to use when a call is\n\t// missing the required ACL auth-method name parameter.\n\terrMissingACLAuthMethodName = errors.New(\"missing ACL auth-method name\")\n\n\t// errMissingACLBindingRuleID is the generic error to use when a call is\n\t// missing the required ACL binding rule ID parameter.\n\terrMissingACLBindingRuleID = errors.New(\"missing ACL binding rule ID\")\n)\n","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/acl.go#L219-L255","documentation":"ExchangeOneTimeToken() expects a OneTimeTokenExchangeResponse containing the exchanged ACL token. If the PUT succeeds but the decoded response is nil, the client returns this error instead of dereferencing a nil pointer. It indicates the server/proxy returned an empty or unparseable success response.","triggerScenarios":"Calling ACLTokens().ExchangeOneTimeToken(secret, q) where the server returns a 200 with an empty body, or a middleware/agent in the path strips the response, leaving resp nil after decoding.","commonSituations":"Request routed to a non-Consul endpoint (wrong address/port) that replies 200 empty; proxy or service mesh stripping bodies; expired one-time secret handled in a way that returns an empty success rather than an error in some setups.","solutions":["Confirm the one-time secret is still valid (one-time tokens are single-use and expire quickly) and retry with a fresh one from UpsertOneTimeToken().","Verify the client's Consul address points at a real Consul server >= 1.6 with ACLs enabled.","Inspect network intermediaries (proxies, gateways) that could return empty 200 responses."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func exchangeRespOK(r *api.OneTimeTokenExchangeResponse) bool { return r != nil && r.Token != nil && r.Token.SecretID != \"\" }","tryCatchPattern":"tok, _, err := client.ACLTokens().ExchangeOneTimeToken(secret, nil)\nif err != nil {\n    if err.Error() == \"no ACL token returned\" {\n        // mint a fresh one-time token and retry once\n    }\n    return err\n}","preventionTips":["One-time tokens are single-use: never retry exchange with the same secret after a failure; mint a new one.","Verify the Consul address points directly at a server, not an intermediary that can return empty bodies."],"tags":["consul","acl","empty-response","one-time-token"],"backgroundTag":"empty-server-response","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}