{"record":{"id":"48b0b7c74dea34de","repo":"multica-ai/multica","slug":"invalid-desktop-runtime-config-expected-a-json-ob","errorCode":null,"errorMessage":"Invalid desktop runtime config: expected a JSON object","messagePattern":"Invalid desktop runtime config: expected a JSON object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/src/shared/runtime-config.ts","lineNumber":64,"sourceCode":"      : deriveWsUrl(apiUrl),\n    appUrl: env.appUrl\n      ? normalizeHttpUrl(env.appUrl, \"VITE_APP_URL\")\n      : deriveDevAppUrl(apiUrl),\n  };\n}\n\nexport function parseRuntimeConfig(raw: string): RuntimeConfig {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch (err) {\n    throw new Error(\n      `Invalid desktop runtime config JSON: ${err instanceof Error ? err.message : \"parse failed\"}`,\n    );\n  }\n\n  if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n    throw new Error(\"Invalid desktop runtime config: expected a JSON object\");\n  }\n\n  const obj = parsed as Record<string, unknown>;\n  if (obj.schemaVersion !== 1) {\n    throw new Error(\"Unsupported desktop runtime config schemaVersion: expected 1\");\n  }\n\n  const apiUrl = requiredString(obj.apiUrl, \"apiUrl\");\n  const appUrl = optionalString(obj.appUrl, \"appUrl\");\n  const wsUrl = optionalString(obj.wsUrl, \"wsUrl\");\n\n  const normalizedApiUrl = normalizeHttpUrl(apiUrl, \"apiUrl\");\n  return {\n    schemaVersion: 1,\n    apiUrl: normalizedApiUrl,\n    wsUrl: wsUrl ? normalizeWsUrl(wsUrl, \"wsUrl\") : deriveWsUrl(normalizedApiUrl),\n    appUrl: appUrl ? normalizeHttpUrl(appUrl, \"appUrl\") : deriveAppUrl(normalizedApiUrl),\n  };","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/apps/desktop/src/shared/runtime-config.ts#L46-L82","documentation":"Wrap thrown by execenv.Prepare when prepareQwenpawWorkspace fails for a 'qwenpaw'-provider task. The daemon materializes <envRoot>/qwenpaw-workspace and seeds it with the task's bound agent skills (params.Task.AgentSkills); a filesystem or skill-writing error in that step aborts Prepare entirely.","triggerScenarios":"Prepare is called with params.Provider == \"qwenpaw\" and prepareQwenpawWorkspace returns an error — e.g. the env-root is not writable, the disk is full, or writing skill files into the workspace fails.","commonSituations":"Daemon running as a user without write access to its env-root; env-root on a full or read-only volume; a skill payload (name/path) that cannot be materialized as files under the workspace dir.","solutions":["Check the wrapped error for the underlying filesystem operation that failed, then verify the daemon user can create directories and files under the task's env-root.","Free disk space or remount the env-root volume read-write.","Inspect the bound agent skills for entries whose files cannot be written (invalid paths, symlink loops) and fix or unbind them.","Re-run the task preparation once the environment issue is corrected."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if params.Provider == \"qwenpaw\" {\n    if err := checkWritable(envRoot); err != nil {\n        return fmt.Errorf(\"env-root not writable before qwenpaw prepare: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"env, err := execenv.Prepare(ctx, params)\nif err != nil && strings.Contains(err.Error(), \"prepare qwenpaw workspace\") {\n    // log wrapped fs error, verify env-root perms/space, then fail the task visibly\n}","preventionTips":["Ensure the daemon user owns the env-root.","Alert on env-root disk usage above a threshold.","Validate skill entries (paths, names) before binding them to qwenpaw agents."],"tags":["go","execenv","qwenpaw","filesystem","skills"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}