{"record":{"id":"e9e2f36fcac52ef5","repo":"different-ai/openwork","slug":"getinstallconfigerrormessage-payload-response-sta","errorCode":null,"errorMessage":"getInstallConfigErrorMessage(payload, response.status)","messagePattern":"getInstallConfigErrorMessage\\(payload, response\\.status\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/_components/install-screen.tsx","lineNumber":167,"sourceCode":"    logoUrl,\n    iconUrl,\n    desktopVersion,\n    distribution,\n  };\n}\n\nasync function fetchInstallConfig(token: string | null) {\n  const path = token ? `/v1/install-config?token=${encodeURIComponent(token)}` : \"/v1/me/install-config\";\n  const { response, payload } = await requestJson(\n    path,\n    { method: \"GET\" },\n    12000,\n  );\n  if (!response.ok) {\n    if (!token && response.status === 401) {\n      throw new Error(\"Sign in to your Den portal to install OpenWork.\");\n    }\n    throw new Error(getInstallConfigErrorMessage(payload, response.status));\n  }\n  const parsed = parseInstallConfig(payload);\n  if (!parsed) {\n    throw new Error(\"This install link returned incomplete setup details.\");\n  }\n  return parsed;\n}\n\nfunction installHref(config: InstallConfig, platform: InstallPlatform, token: string | null) {\n  return token\n    ? buildInstallDownloadHref(config.apiUrl, platform, token)\n    : buildAuthenticatedInstallDownloadHref(config.apiUrl, platform);\n}\n\ntype StepState = \"complete\" | \"active\" | \"pending\";\n\nconst STEP_BADGE: Record<StepState, string> = {\n  complete: \"bg-emerald-50 text-emerald-600\",","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/_components/install-screen.tsx#L149-L185","documentation":"When the /v1/install-config response is not ok and it is not the unauthenticated-401 case, fetchInstallConfig delegates to getInstallConfigErrorMessage: a 404 becomes \"This install link has expired or was replaced...\", and any other status becomes the payload's error message or \"Could not load this install link (<status>)\". The thrown message is that computed string.","triggerScenarios":"Non-ok response other than the no-token 401: 404 (expired/rotated install token), 400 (malformed token), 500 (server error), network-facing proxies returning 502/503.","commonSituations":"Admin regenerated the install link, invalidating the old token (404); stale bookmarked install page; Den API temporarily down (5xx).","solutions":["For 404: request a fresh install link from the workspace admin (Members page) and use the new one.","For 5xx: retry later and check the Den server logs.","Confirm the token in the URL is complete and not URL-truncated (special characters must stay encoded)."],"exampleFix":"// before: old token -> 404 expired\n/v1/install-config?token=OLD\n// after: fresh token from Members page\n/v1/install-config?token=NEW","handlingStrategy":"retry","validationCode":"// pre-check the token shape before calling the API\nif (!/^[A-Za-z0-9_-]+$/.test(token ?? \"\")) throw new Error(\"Install token missing or malformed\");","typeGuard":null,"tryCatchPattern":"try {\n  await fetchInstallConfig(token);\n} catch (err) {\n  if (err.message.includes(\"expired or was replaced\")) {\n    promptRequestFreshLink(); // 404 path\n  } else if (/Could not load this install link \\(5\\d\\d\\)/.test(err.message)) {\n    retryWithBackoff();\n  } else throw err;\n}","preventionTips":["Treat 404 as 'link rotated' and request a fresh link, not a retry.","Keep tokens URL-encoded end-to-end (encodeURIComponent).","Monitor Den API health to distinguish 5xx from bad tokens."],"tags":["http","install","den","expired-link"],"backgroundTag":"token-expired","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}