{"record":{"id":"11ab3dd6dd24f635","repo":"different-ai/openwork","slug":"connector-mapping-not-found","errorCode":"connector_mapping_not_found","errorMessage":"Connector mapping not found.","messagePattern":"Connector mapping not found\\.","errorType":"http","errorClass":"PluginArchRouteFailure","httpStatus":404,"severity":"error","filePath":"ee/apps/den-api/src/routes/org/plugin-system/store.ts","lineNumber":4214,"sourceCode":"    connectorType: target.connectorType,\n    createdAt: new Date(),\n    id: createDenTypeId(\"connectorMapping\"),\n    mappingConfigJson: input.config ?? null,\n    mappingKind: input.mappingKind,\n    objectType: input.objectType,\n    organizationId: input.context.organizationContext.organization.id,\n    pluginId: input.pluginId ?? null,\n    remoteId: null,\n    selector: input.selector.trim(),\n    updatedAt: new Date(),\n  }\n  await db.insert(ConnectorMappingTable).values(row)\n  return serializeConnectorMapping(row)\n}\n\nexport async function updateConnectorMapping(input: { autoAddToPlugin?: boolean; config?: Record<string, unknown>; connectorMappingId: ConnectorMappingId; context: PluginArchActorContext; objectType?: ConnectorMappingRow[\"objectType\"]; pluginId?: PluginId | null; selector?: string }) {\n  const mapping = await getConnectorMappingRow(input.context.organizationContext.organization.id, input.connectorMappingId)\n  if (!mapping) throw new PluginArchRouteFailure(404, \"connector_mapping_not_found\", \"Connector mapping not found.\")\n  await ensureEditableConnectorInstance(input.context, mapping.connectorInstanceId)\n  if (input.pluginId) {\n    await ensureEditablePlugin(input.context, input.pluginId)\n  }\n  await db.update(ConnectorMappingTable).set({\n    autoAddToPlugin: input.autoAddToPlugin ?? mapping.autoAddToPlugin,\n    mappingConfigJson: input.config === undefined ? mapping.mappingConfigJson : input.config,\n    objectType: input.objectType ?? mapping.objectType,\n    pluginId: input.pluginId === undefined ? mapping.pluginId : input.pluginId,\n    selector: input.selector?.trim() || mapping.selector,\n    updatedAt: new Date(),\n  }).where(eq(ConnectorMappingTable.id, mapping.id))\n  return serializeConnectorMapping({ ...mapping, autoAddToPlugin: input.autoAddToPlugin ?? mapping.autoAddToPlugin, mappingConfigJson: input.config === undefined ? mapping.mappingConfigJson : input.config, objectType: input.objectType ?? mapping.objectType, pluginId: input.pluginId === undefined ? mapping.pluginId : input.pluginId, selector: input.selector?.trim() || mapping.selector, updatedAt: new Date() })\n}\n\nexport async function deleteConnectorMapping(input: { connectorMappingId: ConnectorMappingId; context: PluginArchActorContext }) {\n  const mapping = await getConnectorMappingRow(input.context.organizationContext.organization.id, input.connectorMappingId)\n  if (!mapping) throw new PluginArchRouteFailure(404, \"connector_mapping_not_found\", \"Connector mapping not found.\")","sourceCodeStart":4196,"sourceCodeEnd":4232,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/routes/org/plugin-system/store.ts#L4196-L4232","documentation":"Thrown by updateConnectorMapping when getConnectorMappingRow finds no ConnectorMappingRow with the given connectorMappingId in the caller's organization. The update is aborted before permission checks or the db.update call. Like the target lookups, it is org-scoped so cross-org IDs also 404.","triggerScenarios":"Calling updateConnectorMapping with a connectorMappingId that was deleted (e.g. by deleteConnectorMapping), never existed, is mistyped, or belongs to another organization.","commonSituations":"Two admins editing concurrently, one deletes while the other saves; stale list in the UI after a deletion; wrong org selected in an admin console.","solutions":["Re-fetch the mapping list for the org to confirm the ID still exists","Confirm the caller's organization context owns the mapping","Handle the 404 in the UI by refreshing and discarding the stale edit","Recreate the mapping if it was intentionally deleted"],"exampleFix":"// before\nawait updateConnectorMapping({ connectorMappingId: id, context, config: newConfig })\n// after\ntry {\n  await updateConnectorMapping({ connectorMappingId: id, context, config: newConfig })\n} catch (e) {\n  if (isPluginArchRouteFailure(e) && e.code === \"connector_mapping_not_found\") {\n    await refreshMappings() // stale id, reload\n  } else throw e\n}","handlingStrategy":"try-catch","validationCode":"const mappings = await listConnectorMappings({ connectorTargetId: targetId, context })\nif (!mappings.some((m) => m.id === connectorMappingId)) throw new Error(\"mapping no longer exists — refresh\")","typeGuard":"function isConnectorMappingNotFound(e: unknown): boolean {\n  return e instanceof PluginArchRouteFailure && e.code === \"connector_mapping_not_found\"\n}","tryCatchPattern":"try {\n  await updateConnectorMapping({ connectorMappingId, context, config })\n} catch (e) {\n  if (isConnectorMappingNotFound(e)) { await refreshMappingList(); return }\n  throw e\n}","preventionTips":["Reload mappings before editing after any concurrent-change signal","Check mapping IDs against a current list before update","Detect other users' deletes via optimistic concurrency in the UI","Never persist mapping IDs across org switches"],"tags":["http-404","not-found","connectors","concurrency"],"backgroundTag":"resource-not-found","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}