{"record":{"id":"3677d355d3ef292b","repo":"gotify/server","slug":"cannot-parse-token","errorCode":null,"errorMessage":"cannot parse token","messagePattern":"cannot parse token","errorType":"validation","errorClass":"errCannotParseToken","httpStatus":null,"severity":"error","filePath":"auth/token.go","lineNumber":23,"sourceCode":"\t\"crypto/ed25519\"\n\t\"crypto/rand\"\n\t\"crypto/sha512\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nconst (\n\tmaxTimestampDiffSeconds = 15 * 60\n\trandomTokenLength       = 22 // ~2^132 keyspace\n)\n\nvar (\n\terrInvalidToken     = errors.New(\"invalid token\")\n\terrCannotParseToken = errors.New(\"cannot parse token\")\n\terrNoPrivateKey     = errors.New(\"no private key\")\n\ttokenCharacters     = []byte(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_\")\n\tpluginPrefix        = \"P\"\n\tenhancedTokenPrefix = \"gtfy\"\n\n\trandReader = rand.Reader\n)\n\ntype EnhancedToken struct {\n\tident        string\n\tpubOrPrivKey []byte\n\ttimestamp    int64\n\tsignature    []byte\n}\n\n// PublicForm returns the a canonicalized representation of the public key.\nfunc (c *EnhancedToken) PublicForm() string {\n\tif c.timestamp != 0 || len(c.signature) != 0 {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/auth/token.go#L5-L41","documentation":"errCannotParseToken is the sentinel error for tokens that cannot even be parsed as enhanced tokens — most commonly a token that does not start with the required 'gtfy' prefix (wrapped with %w so errors.Is matches). Unlike errInvalidToken (signature failure), this is a structural/format failure. The auth middleware special-cases it to return 401 instead of 500.","triggerScenarios":"Passing a random-plugin token ('P' prefix), a raw random token, an empty string, or an arbitrary string to ParseEnhancedToken or through auth middleware evaluate() where the token can't be parsed.","commonSituations":"Using an old-style plain token after the server switched to enhanced (signed) tokens; env var containing whitespace or a placeholder value; client library version mismatch producing a different token format; pasting a token with surrounding quotes.","solutions":["Verify the token string starts with 'gtfy' for enhanced tokens; if it starts with 'P' or is a plain random token, use the parser/handler for that token type or regenerate an enhanced token","Generate a new enhanced token from the server and store it without modifications (no quotes, no trailing newline)","Trim whitespace/newlines from the token in env/config before use","Check errors.Is(err, errCannotParseToken) to distinguish format problems from signature problems when debugging"],"exampleFix":"// before\nraw := \"\\\"gtfyAbC...\\\"\" // includes quotes\nuser, err := ParseEnhancedToken(raw)\n// after\nraw := strings.TrimSpace(strings.Trim(os.Getenv(\"GITEA_TOKEN\"), \\\"\\\"))\nif !strings.HasPrefix(raw, \"gtfy\") { /* regenerate enhanced token */ }\nuser, err := ParseEnhancedToken(raw)","handlingStrategy":"try-catch","validationCode":"if !strings.HasPrefix(strings.TrimSpace(token), \"gtfy\") {\n    return fmt.Errorf(\"value is not an enhanced token (must start with 'gtfy')\")\n}","typeGuard":"func isEnhancedToken(s string) bool {\n    return strings.HasPrefix(strings.TrimSpace(s), \"gtfy\")\n}","tryCatchPattern":"user, err := ParseEnhancedToken(token)\nif err != nil {\n    if errors.Is(err, errCannotParseToken) {\n        // format problem: wrong prefix, quotes, whitespace, or plain legacy token\n        return nil, fmt.Errorf(\"malformed token %q; regenerate an enhanced token\", summarize(token))\n    }\n    return nil, err\n}","preventionTips":["Trim whitespace and surrounding quotes when loading tokens from env/config","Distinguish token types by prefix: 'gtfy' = enhanced, 'P' = plugin, otherwise legacy random token","After server upgrades that change token format, regenerate stored tokens","Never hardcode placeholder values like 'your-token-here' into production env files"],"tags":["authentication","token","parsing","format"],"backgroundTag":"malformed-token","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}