{"record":{"id":"41b58aa97a1de8d1","repo":"multica-ai/multica","slug":"invalid-token-format-must-start-with-s","errorCode":null,"errorMessage":"invalid token format: must start with %s","messagePattern":"invalid token format: must start with (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_auth.go","lineNumber":41,"sourceCode":")\n\n// loginTokenPrefixes are the token prefixes `multica login --token` accepts.\n// The CLI used to hardcode `mul_` only, which made it impossible to log in\n// with a Multica Cloud Node PAT (`mcn_`) even though the server happily\n// authenticates both kinds. Keep this list in sync with the prefix branches\n// in server/internal/middleware/auth.go.\nvar loginTokenPrefixes = []string{\"mul_\", auth.CloudPATPrefix}\n\n// validateLoginTokenPrefix returns nil if token starts with one of the\n// CLI-recognised PAT prefixes, or an error describing the accepted set.\n// Extracted so the prefix list has one obvious test surface.\nfunc validateLoginTokenPrefix(token string) error {\n\tfor _, p := range loginTokenPrefixes {\n\t\tif strings.HasPrefix(token, p) {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"invalid token format: must start with %s\", strings.Join(loginTokenPrefixes, \" or \"))\n}\n\nvar authCmd = &cobra.Command{\n\tUse:   \"auth\",\n\tShort: \"Authenticate multica with Multica\",\n}\n\nvar authStatusCmd = &cobra.Command{\n\tUse:   \"status\",\n\tShort: \"Show current authentication status\",\n\tRunE:  runAuthStatus,\n}\n\nvar authLogoutCmd = &cobra.Command{\n\tUse:   \"logout\",\n\tShort: \"Remove stored authentication token\",\n\tRunE:  runAuthLogout,\n}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_auth.go#L23-L59","documentation":"During token login the CLI validates that the supplied personal access token starts with one of the recognized prefixes (mul_ or the cloud PAT prefix, per loginTokenPrefixes). Any other shape is rejected before a network call is made, so users get immediate feedback instead of an opaque 401.","triggerScenarios":"Passing `--token` with a JWT, a session cookie, a paste that lost its first characters, whitespace-merged text, or a token issued for a different auth system (e.g. an API key from another product).","commonSituations":"Copy-paste truncation (missing the mul_ prefix); pasting the token label/description instead of the value; using an OAuth id_token from browser sign-in instead of a PAT; tokens from an older server format.","solutions":["Re-copy the token from its source, ensuring the mul_ (or cloud PAT) prefix is included and no extra characters are selected","Paste into a text editor first to verify it is a single line with the correct prefix","If your token genuinely has another prefix, regenerate a PAT from the current product UI"],"exampleFix":"# before\nmultica login --token eyJhbGciOi...   # JWT, wrong shape\n\n# after\nmultica login --token mul_ABCdef123...","handlingStrategy":"validation","validationCode":"# shell: check prefix before login\ncase \"$MULTICA_TOKEN\" in mul_*|\"$(cloud prefix)\"*) ;; *) echo 'token must start with mul_ or the cloud PAT prefix' >&2; exit 1;; esac\nmultica login --token \"$MULTICA_TOKEN\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store PATs in a secret manager and paste from there, never from chat screenshots","Trim whitespace and verify the prefix visually before submitting"],"tags":["cli","auth","validation","token"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}