{"record":{"id":"2a6fe585b75249b8","repo":"different-ai/openwork","slug":"failurelabel-response-status","errorCode":null,"errorMessage":"${failureLabel} (${response.status}).","messagePattern":"\\$\\{failureLabel\\} \\(\\$\\{response\\.status\\}\\)\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/plugin-editor-screen.tsx","lineNumber":116,"sourceCode":"    input: {\n      rawSourceText:\n        component.kind === \"skill\" ? buildSkillMarkdown(component) : `${component.content.trim()}\\n`,\n      metadata: {\n        name: component.name.trim(),\n        description: component.description.trim() || undefined,\n      },\n    },\n  };\n}\n\nasync function postJson(path: string, body: unknown, failureLabel: string): Promise<unknown> {\n  const { response, payload } = await requestJson(\n    path,\n    { method: \"POST\", body: JSON.stringify(body) },\n    20000,\n  );\n  if (!response.ok) {\n    throw getRequestError(payload, response, `${failureLabel} (${response.status}).`);\n  }\n  return payload;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null;\n}\n\nfunction createdItemId(payload: unknown): string | null {\n  const item = isRecord(payload) && isRecord(payload.item) ? payload.item : null;\n  return typeof item?.id === \"string\" ? item.id : null;\n}\n\nexport function PluginEditorScreen() {\n  const router = useRouter();\n  const searchParams = useSearchParams();\n  const queryClient = useQueryClient();\n  const { orgContext, orgSlug, runReauthableAction } = useOrgDashboard();","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/plugin-editor-screen.tsx#L98-L134","documentation":"postJson in plugin-editor-screen.tsx is a shared helper that POSTs a JSON body and throws getRequestError with a caller-supplied failureLabel when the response is not ok. The message becomes e.g. 'Failed to create Plugin (500).'. It is a generic wrapper: the status code and payload carry the actual diagnostic.","triggerScenarios":"Any createPlugin POST via postJson returning 4xx/5xx: validation failure (400) on plugin draft fields, unauthorized session (401), missing permissions (403), name conflict (409), or gateway error (502/504). 20s request timeout also lands here.","commonSituations":"Submitting the plugin editor with an invalid draft (missing name/description constraints); duplicated plugin slug; Den API deploy in progress; long-running create exceeding the 20s timeout behind a slow upstream.","solutions":["Inspect the status in the message and the server payload for field-level validation errors; fix the draft accordingly.","For 401, re-authenticate; for 403, verify plugin-create permission in the org.","If 502/504 or timeout, check Den server health and retry once.","Ensure the plugin name/slug is unique in the org before resubmitting."],"exampleFix":"// before: resubmitting identical draft blindly\nawait createPlugin(draft);\n// after: guard obvious client-side validation first\nif (!draft.name?.trim()) throw new Error('Plugin name is required.');\nawait createPlugin(draft);","handlingStrategy":"validation","validationCode":"const errors = validatePluginDraft(draft); // zod schema for name, description, server keys\nif (!errors.success) throw new Error('Fix draft errors before creating: ' + errors.error.message);","typeGuard":"function isPluginDraft(v: unknown): v is { name: string; selectedServerKeys: string[] } {\n  return typeof v === 'object' && v !== null &&\n    typeof (v as Record<string, unknown>).name === 'string' &&\n    Array.isArray((v as Record<string, unknown>).selectedServerKeys);\n}","tryCatchPattern":"try {\n  const item = await createPlugin(draft);\n  router.push(`/plugins/${item.id}`);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (/\\(400\\)/.test(msg)) toast('Check the highlighted fields and resubmit.');\n  else if (/\\(409\\)/.test(msg)) toast('A plugin with this name already exists.');\n  else toast(msg);\n}","preventionTips":["Validate the draft client-side (zod) before POSTing to avoid 400s.","Enforce unique plugin names/slugs in the form before submit.","Show server payload field errors next to form fields, not just a toast.","Increase timeout or add optimistic UI if creates routinely approach 20s."],"tags":["http","api","plugin-editor","validation"],"backgroundTag":"http-non-ok-response","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}