{"record":{"id":"9773ff5780ee04cd","repo":"different-ai/openwork","slug":"failed-to-load-plugin-contents-membershipsresul","errorCode":null,"errorMessage":"Failed to load plugin contents (${membershipsResult.response.status}).","messagePattern":"Failed to load plugin contents \\((.+?)\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/plugin-data.tsx","lineNumber":626,"sourceCode":"    case \"Notification\":\n    case \"Stop\":\n      return value;\n    default:\n      return \"Notification\";\n  }\n}\n\nasync function fetchResolvedPlugin(id: string): Promise<DenPlugin | null> {\n  const [pluginResult, membershipsResult] = await Promise.all([\n    requestJson(`/v1/plugins/${encodeURIComponent(id)}`, { method: \"GET\" }, 15000),\n    requestJson(`/v1/plugins/${encodeURIComponent(id)}/resolved`, { method: \"GET\" }, 15000),\n  ]);\n\n  if (!pluginResult.response.ok) {\n    throw new Error(getErrorMessage(pluginResult.payload, `Failed to load plugin (${pluginResult.response.status}).`));\n  }\n  if (!membershipsResult.response.ok) {\n    throw new Error(getErrorMessage(membershipsResult.payload, `Failed to load plugin contents (${membershipsResult.response.status}).`));\n  }\n\n  const pluginItem = isRecord(pluginResult.payload) && isRecord(pluginResult.payload.item) ? pluginResult.payload.item : null;\n  if (!pluginItem) {\n    return null;\n  }\n\n  const pluginId = asString(pluginItem.id);\n  const name = asString(pluginItem.name);\n  if (!pluginId || !name) {\n    return null;\n  }\n\n  const membershipItems = isRecord(membershipsResult.payload) && Array.isArray(membershipsResult.payload.items)\n    ? membershipsResult.payload.items.map(parseMembershipConfigObject).filter((value): value is NonNullable<typeof value> => Boolean(value))\n    : [];\n\n  const skills = membershipItems","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/plugin-data.tsx#L608-L644","documentation":"Same fetchResolvedPlugin flow: after the plugin detail request succeeds, a non-2xx from GET /v1/plugins/:id/resolved (plugin membership/contents) throws this error with the status embedded in the fallback message. It is checked only after the plugin fetch succeeds, so the plugin itself exists but its resolved contents could not be loaded.","triggerScenarios":"GET /v1/plugins/{id}/resolved returns 401/403 (user can see the plugin but lacks permission to list its memberships/contents), 404 (contents endpoint unavailable or version mismatch on the Den server), or 5xx during content resolution.","commonSituations":"A role downgraded to viewer without membership-read rights; self-hosted Den server older than the resolved-contents endpoint; transient 5xx while the server resolves many plugin memberships; the plugin just published and its contents not yet propagated.","solutions":["Check the response status: 403 means fix org permissions for the current user (membership read access).","Retry after transient 5xx; inspect Den server logs for the resolution failure.","Upgrade a self-hosted Den server if /v1/plugins/{id}/resolved returns 404/405 (endpoint missing).","Re-open the plugin after republishing if the contents were mid-publication."],"exampleFix":"// before: contents error only distinguishes via status string\nif (!membershipsResult.response.ok) {\n  throw new Error(getErrorMessage(membershipsResult.payload, `Failed to load plugin contents (${membershipsResult.response.status}).`));\n}\n// after: degrade gracefully when contents cannot be read\nif (!membershipsResult.response.ok) {\n  if (membershipsResult.response.status === 403) {\n    return buildPluginWithoutContents(pluginItem);\n  }\n  throw new Error(getErrorMessage(membershipsResult.payload, `Failed to load plugin contents (${membershipsResult.response.status}).`));\n}","handlingStrategy":"fallback","validationCode":"const membershipReadable = await canCurrentUser(\"plugin.memberships.read\", orgSlug);\nif (!membershipReadable) return buildPluginWithoutContents(pluginId);","typeGuard":"function hasItemsPayload(p: unknown): p is { items: unknown[] } {\n  return typeof p === \"object\" && p !== null && Array.isArray((p as { items?: unknown }).items);\n}","tryCatchPattern":"try {\n  resolved = await requestJson(`/v1/plugins/${id}/resolved`, { method: \"GET\" }, 15000);\n} catch {\n  resolved = null; // degrade: render plugin detail without contents\n}\nif (!resolved?.response.ok) resolved = null;","preventionTips":["Render the plugin detail even when contents fail; mark contents as unavailable.","Grant viewer roles membership-read permission if contents should be visible org-wide.","Add a retry with backoff for the resolved endpoint; it can 5xx under load.","Monitor Den server version drift — a missing /resolved endpoint means upgrade the server."],"tags":["http","api-client","den-web","plugin-contents"],"backgroundTag":"http-request-failed-with-status","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}