{"record":{"id":"3df6f2bfdc15d577","repo":"different-ai/openwork","slug":"extensions-add-sign-in-required","errorCode":"extensions.add_sign_in_required","errorMessage":"extensions.add_sign_in_required","messagePattern":"extensions\\.add_sign_in_required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/app/src/react-app/domains/settings/state/extensions-store.ts","lineNumber":2268,"sourceCode":"        throw new Error(t(\"extensions.add_mcp_url_required\"));\n      }\n    } else if (kind !== \"plugin\") {\n      if (!description) {\n        throw new Error(t(\"extensions.add_description_required\"));\n      }\n      if (!instructions) {\n        throw new Error(t(\"extensions.add_instructions_required\"));\n      }\n    }\n    if (kind === \"plugin\" && drafts.length === 0) {\n      throw new Error(t(\"extensions.add_plugin_component_required\"));\n    }\n\n    const settings = readDenSettings();\n    const token = settings.authToken?.trim() ?? \"\";\n    const orgId = settings.activeOrgId?.trim() ?? \"\";\n    if (!token || !orgId) {\n      throw new Error(t(\"extensions.add_sign_in_required\"));\n    }\n    const client = createDenClient({\n      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;","sourceCodeStart":2250,"sourceCodeEnd":2286,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/settings/state/extensions-store.ts#L2250-L2286","documentation":"Publishing a library item to an organization requires Den authentication: readDenSettings() must yield both an authToken and an activeOrgId. If either is missing/blank, createLibraryItem throws the localized t('extensions.add_sign_in_required') before creating the Den client.","triggerScenarios":"Calling createLibraryItem after all field validations pass while the user is signed out of Den, or signed in but with no active organization selected (settings.authToken or settings.activeOrgId empty).","commonSituations":"Token expired and cleared from settings but the UI still allows the add dialog; fresh install where the user never signed into Den; org selection lost after settings reset or workspace switch.","solutions":["Sign in to Den (Account → Sign in) so settings.authToken is populated, then retry.","Select an active organization in settings so activeOrgId is set.","Persist/refresh Den settings before opening the publish flow; gate the submit button on token && orgId being present.","Handle 401 follow-ups separately — this specific error means credentials were absent, not rejected."],"exampleFix":"// before\nawait createLibraryItem('skill', input); // throws when signed out\n// after\nconst settings = readDenSettings();\nif (!settings.authToken?.trim() || !settings.activeOrgId?.trim()) {\n  openSignInDialog();\n  return;\n}\nawait createLibraryItem('skill', input);","handlingStrategy":"validation","validationCode":"const settings = readDenSettings();\nif (!settings.authToken?.trim() || !settings.activeOrgId?.trim()) {\n  openSignInDialog(); return;\n}","typeGuard":"function isDenAuthenticated(s: { authToken?: string | null; activeOrgId?: string | null }): boolean {\n  return !!s.authToken?.trim() && !!s.activeOrgId?.trim();\n}","tryCatchPattern":"try {\n  await createLibraryItem(kind, input);\n} catch (e) {\n  if (e instanceof Error && e.message === t('extensions.add_sign_in_required')) {\n    openSignInDialog();\n  } else throw e;\n}","preventionTips":["Gate publish actions on Den auth state in the UI","Refresh the token before opening the publish dialog","Require active org selection as part of onboarding","Distinguish missing-credentials from 401 (extensions.add_unauthorized) when handling failures"],"tags":["auth","den","sign-in"],"backgroundTag":"authentication-required","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}