{"record":{"id":"42a87546addd1a11","repo":"sipeed/picoclaw","slug":"failed-to-load-launcher-config-v","errorCode":null,"errorMessage":"Failed to load launcher config: %v","messagePattern":"Failed to load launcher config: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"web/backend/api/launcher_config.go","lineNumber":57,"sourceCode":"\t\tport = launcherconfig.DefaultPort\n\t}\n\treturn launcherconfig.Config{\n\t\tPort:                 port,\n\t\tPublic:               h.serverPublic,\n\t\tAllowedCIDRs:         append([]string(nil), h.serverCIDRs...),\n\t\tAllowLocalhostBypass: h.serverAllowLocalhostBypass,\n\t\tTrustedProxyCIDRs:    append([]string(nil), h.serverTrustedProxyCIDRs...),\n\t}\n}\n\nfunc (h *Handler) loadLauncherConfig() (launcherconfig.Config, error) {\n\treturn launcherconfig.Load(h.launcherConfigPath(), h.launcherFallbackConfig())\n}\n\nfunc (h *Handler) handleGetLauncherConfig(w http.ResponseWriter, r *http.Request) {\n\tcfg, err := h.loadLauncherConfig()\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to load launcher config: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tjson.NewEncoder(w).Encode(launcherConfigPayload{\n\t\tPort:                 cfg.Port,\n\t\tPublic:               cfg.Public,\n\t\tAllowedCIDRs:         append([]string(nil), cfg.AllowedCIDRs...),\n\t\tAllowLocalhostBypass: cfg.AllowLocalhostBypass,\n\t\tTrustedProxyCIDRs:    append([]string(nil), cfg.TrustedProxyCIDRs...),\n\t})\n}\n\nfunc (h *Handler) handleUpdateLauncherConfig(w http.ResponseWriter, r *http.Request) {\n\tvar payload launcherConfigUpdatePayload\n\tif err := json.NewDecoder(r.Body).Decode(&payload); err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Invalid JSON: %v\", err), http.StatusBadRequest)\n\t\treturn","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/web/backend/api/launcher_config.go#L39-L75","documentation":"Returned by GET /api/system/launcher-config when launcherconfig.Load of launcher-config.json (path derived via PathForAppConfig next to the app config) fails. From launcherconfig/config.go:102-124: a missing file is fine (server-flag fallback is returned); errors come from reading the file (permission, I/O), invalid JSON, or on-disk values failing Validate - port outside 1-65535, or a CIDR entry that net.ParseCIDR rejects.","triggerScenarios":"launcher-config.json hand-edited with a JSON typo; port edited to 0 or 70000; a CIDR written as a bare IP like \"192.168.1.5\" instead of \"192.168.1.5/32\"; file owned by root:0600 while the backend runs unprivileged.","commonSituations":"Sysadmins hand-editing the file instead of using the PUT endpoint; restoring a backup with wrong ownership; schema drift after version upgrades.","solutions":["Read the wrapped error: a JSON syntax error points at editing damage; a Validate error names the offending port or CIDR","Fix the named field, or simply delete launcher-config.json - that is safe, the handler falls back to the server's startup flags","Ensure the backend process can read the file (ownership and mode)","Afterward use PUT /api/system/launcher-config for changes so values are always validated before persistence"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let res = await fetch('/api/system/launcher-config');\nif (res.status === 500) {\n  const detail = await res.text();\n  // File-side corruption cannot be fixed through the API - offer a reset action:\n  if (confirm('launcher-config.json is unreadable (' + detail + '). Delete it on the server to restore defaults?')) {\n    await serverSideResetLauncherConfig();   // rm the file; GET then falls back to startup flags\n    res = await fetch('/api/system/launcher-config');\n  }\n}","preventionTips":["Only modify launcher settings through PUT /api/system/launcher-config - it validates before persisting","Keep launcher-config.json owned by the service user with mode 0600","Include GET launcher-config in health checks to catch corruption early"],"tags":["config","json","launcher","validation","go"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}