{"record":{"id":"0c54c5c355a55334","repo":"Tencent/WeKnora","slug":"failed-to-allocate-unique-resource-access-token","errorCode":null,"errorMessage":"failed to allocate unique resource access token","messagePattern":"failed to allocate unique resource access token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/resource.go","lineNumber":235,"sourceCode":"\t// derived one is not usable. Mint a fresh random token.\n\tfor attempt := 0; attempt < 4; attempt++ {\n\t\ttoken, tokenErr := randomResourceToken()\n\t\tif tokenErr != nil {\n\t\t\treturn \"\", tokenErr\n\t\t}\n\t\tgrant := &types.ResourceAccessGrant{\n\t\t\tTokenHash:   resourceLocationHash(token),\n\t\t\tResourceID:  resource.ID,\n\t\t\tAccessScope: \"read\",\n\t\t\tExpiresAt:   time.Now().UTC().Add(ttl),\n\t\t}\n\t\tif err := s.repo.CreateGrant(ctx, grant); err == nil {\n\t\t\treturn token, nil\n\t\t} else if !isUniqueViolation(err) {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"failed to allocate unique resource access token\")\n}\n\n// reuseOrCreateDerivedGrant returns the token of a live grant for resourceID,\n// creating the row on first use within the current window. It returns (\"\", nil)\n// when the caller must fall back to a random token.\n//\n// The token is derived rather than random so it can be recomputed without ever\n// storing it: the table holds only the hash, as before, and the plaintext token\n// cannot be reconstructed from a database dump without SYSTEM_AES_KEY.\n// Authorization still lives entirely in the row — a revoked or expired grant\n// stops resolving even though the token derives to the same value.\nfunc (s *resourceCatalog) reuseOrCreateDerivedGrant(\n\tctx context.Context, resourceID string, ttl time.Duration,\n) (string, error) {\n\ttoken, expiresAt, ok := derivedGrantToken(resourceID, ttl)\n\tif !ok {\n\t\treturn \"\", nil\n\t}","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/resource.go#L217-L253","documentation":"CreateAccessGrant retries inserting a grant with a freshly generated random token; on repeated unique-constraint violations it exhausts the loop and returns this error. It means the token generator collided with existing tokens on every attempt — astronomically unlikely randomly, so it usually indicates seeded/deterministic tokens or a broken entropy source.","triggerScenarios":"Loop of repo.CreateGrant calls each failing with isUniqueViolation(err) until attempts run out; caused by deterministic token seeds, mocking a weak random source, or many tokens with tiny keyspace.","commonSituations":"Test environments with a fixed rand seed; clock-based token generation; config that shrinks the token alphabet/length; duplicate grant rows never cleaned up.","solutions":["Verify token generation uses crypto/rand with sufficient entropy (not a seeded/time-based source)","Retry the whole CreateAccessGrant call once; a transient collision resolving between attempts is fine","Audit and prune stale/duplicate grant rows in the repo","Increase token length/alphabet if the keyspace is small"],"exampleFix":"// before\ntoken := fmt.Sprintf(\"tok-%d\", time.Now().UnixNano())\n// after\ntoken := \"tok-\" + base64.RawURLEncoding.EncodeToString(randomBytes(32))","handlingStrategy":"retry","validationCode":"// No caller-side validation possible; ensure token source quality before calling.\nif !highEntropyToken(token) { return errors.New(\"token generator too weak\") }","typeGuard":"func highEntropyToken(t string) bool { return len(t) >= 32 }","tryCatchPattern":"token, err := catalog.CreateAccessGrant(ctx, ref, ttl)\nif err != nil && strings.Contains(err.Error(), \"failed to allocate unique resource access token\") {\n    return ErrTokenExhausted // alert: entropy source likely broken\n}","preventionTips":["Use crypto/rand for token generation","Avoid seeded rand in test harnesses that later run in prod-like paths","Keep token length >= 128 bits","Alert on this error: a single occurrence suggests systemic token collision"],"tags":["access-token","uniqueness","entropy"],"backgroundTag":"unique-token-generation-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}