{"record":{"id":"a1dfdf8aee355c33","repo":"multica-ai/multica","slug":"workspace-id-slug-or-id-prefix-is-required","errorCode":null,"errorMessage":"workspace id, slug, or id prefix is required","messagePattern":"workspace id, slug, or id prefix is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_workspace.go","lineNumber":362,"sourceCode":"\n\tvar ws map[string]any\n\tif err := client.PostJSON(ctx, \"/api/workspaces\", body, &ws); err != nil {\n\t\treturn fmt.Errorf(\"create workspace: %w\", err)\n\t}\n\treturn printWorkspace(cmd, ws)\n}\n\n// resolveWorkspaceByIDOrSlug looks up a workspace in the caller's accessible\n// list by full UUID, slug (case-insensitive), or short UUID prefix (≥4 hex\n// chars). The matching order is exact UUID → exact slug → prefix, so a slug\n// that happens to be a hex string can never be shadowed by a colliding UUID\n// prefix. Returns an error if no workspace matches, which doubles as the\n// \"access denied / does not exist\" check — the server only returns workspaces\n// the user is a member of, so a match implies access.\nfunc resolveWorkspaceByIDOrSlug(workspaces []workspaceSummary, target string) (workspaceSummary, error) {\n\ttarget = strings.TrimSpace(target)\n\tif target == \"\" {\n\t\treturn workspaceSummary{}, fmt.Errorf(\"workspace id, slug, or id prefix is required\")\n\t}\n\t// Slug comparison is case-insensitive (slugs are stored lowercase on the\n\t// server, but tolerate user-typed uppercase). UUIDs are also case-\n\t// insensitive in canonical form, so the lowering is safe for both.\n\tlowered := strings.ToLower(target)\n\tfor _, ws := range workspaces {\n\t\tif strings.ToLower(ws.ID) == lowered {\n\t\t\treturn ws, nil\n\t\t}\n\t}\n\tfor _, ws := range workspaces {\n\t\tif ws.Slug != \"\" && strings.ToLower(ws.Slug) == lowered {\n\t\t\treturn ws, nil\n\t\t}\n\t}\n\n\t// Fall back to short UUID prefix matching, so values copied from\n\t// `workspace list`'s default (truncated) ID column round-trip back into","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_workspace.go#L344-L380","documentation":"resolveWorkspaceByIDOrSlug was called with an empty target (after trimming). This helper resolves UUID / slug / prefix identifiers for workspace subcommands, and an empty string cannot identify anything, so it fails before fetching the workspace list.","triggerScenarios":"Reached via resolveWorkspaceRef when a workspace subcommand (get/update/member list/switch) received an empty or whitespace-only identifier argument. Usually the argument itself is guarded earlier, so this is the last-resort backstop.","commonSituations":"Scripts passing an unset positional variable, e.g. `multica workspace get \"$WS\"` with WS empty.","solutions":["Pass a non-empty identifier: full UUID, slug, or a short UUID prefix of at least 4 hex chars.","Set MULTICA_WORKSPACE_ID where the command supports it, or run `multica workspace switch` once to establish a default.","Script guard: fail before invoking when the identifier variable is empty."],"exampleFix":"# before\nmultica workspace get \"\"\n\n# after\nmultica workspace get my-team   # or a UUID / ≥4-char UUID prefix","handlingStrategy":"validation","validationCode":"WS=\"$(echo \"$WS\" | tr -d ' ')\"\n[ -n \"$WS\" ] || { echo 'workspace identifier required'; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set MULTICA_WORKSPACE_ID or run `workspace switch` once per environment.","Validate identifier variables are non-empty before passing them positionally."],"tags":["cli","validation","workspace"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}