{"record":{"id":"3715ecbada14d92a","repo":"multica-ai/multica","slug":"not-authenticated-run-multica-login-first-s","errorCode":null,"errorMessage":"not authenticated: run 'multica login' first%s","messagePattern":"not authenticated: run 'multica login' first(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_workspace.go","lineNumber":229,"sourceCode":"}\n\n// workspaceSummary is the subset of fields the CLI needs from /api/workspaces\n// to drive list and switch. Keeping it here (instead of using the full\n// WorkspaceResponse) avoids a dependency on the handler package.\ntype workspaceSummary struct {\n\tID   string `json:\"id\"`\n\tName string `json:\"name\"`\n\tSlug string `json:\"slug\"`\n}\n\n// fetchWorkspaces lists all workspaces the authenticated user belongs to. It\n// is shared by `list` and `switch` so both see the same access-controlled view\n// of workspaces.\nfunc fetchWorkspaces(ctx context.Context, cmd *cobra.Command) ([]workspaceSummary, error) {\n\tserverURL := resolveServerURL(cmd)\n\ttoken := resolveToken(cmd)\n\tif token == \"\" {\n\t\treturn nil, fmt.Errorf(\"not authenticated: run 'multica login' first%s\", daemonPortOnlyContextHint())\n\t}\n\n\tclient := cli.NewAPIClient(serverURL, \"\", token)\n\tvar workspaces []workspaceSummary\n\tif err := client.GetJSON(ctx, \"/api/workspaces\", &workspaces); err != nil {\n\t\treturn nil, fmt.Errorf(\"list workspaces: %w\", err)\n\t}\n\treturn workspaces, nil\n}\n\nfunc runWorkspaceList(cmd *cobra.Command, _ []string) error {\n\tctx, cancel := cli.APIContext(context.Background())\n\tdefer cancel()\n\n\tworkspaces, err := fetchWorkspaces(ctx, cmd)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_workspace.go#L211-L247","documentation":"Shared helper fetchWorkspaces (used by `workspace list` and `workspace switch`) found no auth token: resolveToken returned an empty string for both the flag/env and stored credential. The suffix from daemonPortOnlyContextHint adds context when only a daemon port mismatch is involved.","triggerScenarios":"Running `multica workspace list` or `workspace switch` before ever running `multica login`, or after the stored token file was removed, with no --token flag / MULTICA_TOKEN-style env override.","commonSituations":"Fresh installs, CI containers with no credential store, home-dir permission issues that silently prevent token persistence, or multiple profiles where login was done under a different user.","solutions":["Run `multica login` to obtain and store a token.","If scripting/CI, supply the token explicitly via the token flag or environment variable instead of relying on the store.","If you already logged in, verify the credential file exists and is readable by the current OS user (no permission errors in `multica login` output)."],"exampleFix":"# before\nmultica workspace list   # not authenticated\n\n# after\nmultica login && multica workspace list","handlingStrategy":"validation","validationCode":"command -v multica >/dev/null && multica login --check 2>/dev/null || echo 'no stored token; run multica login'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `multica login` as the first step of any scripted session.","In CI, inject the token via env/flag rather than relying on the credential store.","Confirm the credential file's user/permissions after OS user changes."],"tags":["cli","auth","workspace"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}