{"record":{"id":"c875b7420259365a","repo":"different-ai/openwork","slug":"extensions-add-unauthorized","errorCode":"extensions.add_unauthorized","errorMessage":"extensions.add_unauthorized","messagePattern":"extensions\\.add_unauthorized","errorType":"exception","errorClass":"DenApiError","httpStatus":401,"severity":"error","filePath":"apps/app/src/react-app/domains/settings/state/extensions-store.ts","lineNumber":2289,"sourceCode":"      baseUrl: settings.baseUrl,\n      token,\n    });\n    const body = denLibraryPluginCreateRequest(kind, {\n      ...input,\n      components: kind === \"plugin\" ? drafts : input.components,\n    });\n    try {\n      await client.setActiveOrganization({ organizationId: orgId });\n      const pluginId = await client.createOrgPlugin(orgId, body);\n      await waitForListedLibraryPlugin(\n        () => client.listMeLibraryPlugins(orgId),\n        pluginId,\n      );\n      clearCloudInventoryCache();\n      return pluginId;\n    } catch (error) {\n      if (error instanceof DenApiError && error.status === 401) {\n        throw new Error(t(\"extensions.add_unauthorized\"));\n      }\n      throw error;\n    }\n  }\n\n  function abortRefreshes() {\n    refreshSkillsAborted = true;\n    refreshPluginsAborted = true;\n    refreshCloudOrgMarketplacesAborted = true;\n  }\n\n  function ensureSkillsFresh() {\n    if (!snapshot.skillsStale) return;\n    void refreshSkills({ force: true });\n  }\n\n  function ensurePluginsFresh(scopeOverride?: PluginScope) {\n    if (!snapshot.pluginsStale) return;","sourceCodeStart":2271,"sourceCodeEnd":2307,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/settings/state/extensions-store.ts#L2271-L2307","documentation":"Thrown by the extensions store when adding a plugin/extension fails because the Den API rejected the request with HTTP 401. The store catches DenApiError with status 401 and rethrows a localized 'extensions.add_unauthorized' message so the settings UI shows a friendly auth error instead of a raw API error. Any other error is rethrown unchanged.","triggerScenarios":"Calling the store's add-extension action while the user's Den session token is missing, expired, or revoked; the underlying Den API call (which then calls clearCloudInventoryCache() on success) returns 401.","commonSituations":"User signed out of Den or their cloud session expired while the settings page stayed open; token rotated server-side; app started without completing cloud sign-in and the user attempts to install a cloud plugin.","solutions":["Re-authenticate with Den (Account → Sign in / paste sign-in code) and retry the add.","Refresh the cloud inventory/token state before retrying (clearCloudInventoryCache runs on success anyway).","Check the plugin's Den API endpoint and token configuration if 401 persists for a freshly signed-in user."],"exampleFix":"// before\nthrow new Error(t(\"extensions.add_unauthorized\"));\n// after — prompt re-auth flow instead of a dead-end error\nif (error instanceof DenApiError && error.status === 401) {\n  await requestDenSignIn();\n  return addPlugin(pluginId); // retry once after re-auth\n}","handlingStrategy":"try-catch","validationCode":"const authed = await denApi.whoami().then(() => true, () => false);\nif (!authed) await requestDenSignIn();","typeGuard":"function isDenAuthError(e: unknown): e is DenApiError {\n  return e instanceof DenApiError && e.status === 401;\n}","tryCatchPattern":"try {\n  await extensionsStore.add(pluginId);\n} catch (error) {\n  if (error instanceof DenApiError && error.status === 401) {\n    await requestDenSignIn(); // re-auth then retry\n  } else throw error;\n}","preventionTips":["Check Den session validity before showing add-plugin actions.","Wire a re-auth prompt on any 401 instead of a dead-end message.","Refresh tokens proactively before they expire."],"tags":["auth","http-401","den-api","plugins"],"backgroundTag":"http-401-unauthorized","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}