{"record":{"id":"046be3c58be3eb65","repo":"different-ai/openwork","slug":"scope-must-be-project-or-global","errorCode":null,"errorMessage":"scope must be 'project' or 'global'","messagePattern":"scope must be 'project' or 'global'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/main.mjs","lineNumber":1468,"sourceCode":"    runtimeBootstrapPromise = bootRuntimeForSelectedWorkspace().catch((error) => ({\n      ok: false,\n      error: error instanceof Error ? error.message : String(error),\n    }));\n  }\n  return runtimeBootstrapPromise;\n}\n\nfunction resolveOpencodeConfigPath(scope, projectDir) {\n  if (scope === \"project\") {\n    if (!String(projectDir ?? \"\").trim()) {\n      throw new Error(\"projectDir is required\");\n    }\n    return workspaceOpencodeConfigCandidates(projectDir);\n  } else if (scope === \"global\") {\n    const root = globalOpencodeRoot();\n    return [path.join(root, \"opencode.jsonc\"), path.join(root, \"opencode.json\")];\n  } else {\n    throw new Error(\"scope must be 'project' or 'global'\");\n  }\n}\n\nasync function selectOpencodeConfigPath(candidates) {\n  for (const candidate of candidates) {\n    if (await pathExists(candidate)) return candidate;\n  }\n  return candidates[0];\n}\n\nasync function readOpencodeConfig(scope, projectDir) {\n  const chosenPath = await selectOpencodeConfigPath(resolveOpencodeConfigPath(scope, projectDir));\n  const exists = await pathExists(chosenPath);\n  return {\n    path: chosenPath,\n    exists,\n    content: exists ? await readFile(chosenPath, \"utf8\") : null,\n  };","sourceCodeStart":1450,"sourceCodeEnd":1486,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/main.mjs#L1450-L1486","documentation":"resolveOpencodeConfigPath only accepts scope values 'project' or 'global'; anything else falls into the final else and throws. This is an explicit argument validation to prevent silently resolving config in an unintended location.","triggerScenarios":"Calling a config-path API with scope misspelled ('Project', 'workspace', 'user'), undefined/null scope, or a scope value carried over from the commands API which uses 'workspace' instead of 'project'.","commonSituations":"Copy-pasting code between the commands API (scope 'workspace'|'global') and the config API (scope 'project'|'global'), typos in string literals, or dynamic scope values derived from unvalidated settings.","solutions":["Change scope to exactly 'project' or 'global' (lowercase).","If the call came from commands-style code using 'workspace', switch it to 'project' for config APIs.","Validate/normalize the scope string at the call site before invoking.","Use a union type or constant enum for scope in renderer code so invalid values fail at compile time."],"exampleFix":"// before\nawait resolveOpencodeConfigPath(\"workspace\", dir);\n// after\nawait resolveOpencodeConfigPath(\"project\", dir);","handlingStrategy":"validation","validationCode":"const VALID_CONFIG_SCOPES = ['project', 'global'];\nif (!VALID_CONFIG_SCOPES.includes(scope)) {\n  throw new Error(`scope must be one of ${VALID_CONFIG_SCOPES.join(', ')}, got ${scope}`);\n}","typeGuard":"function isConfigScope(scope) {\n  return scope === 'project' || scope === 'global';\n}","tryCatchPattern":null,"preventionTips":["Share scope constants between the config and commands APIs to avoid 'project' vs 'workspace' drift.","Use union types or enums in renderer code so invalid scopes fail at compile time.","Never build scope strings dynamically from unvalidated settings input."],"tags":["validation","arguments","enum-value"],"backgroundTag":"invalid-argument-value","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}