different-ai/openwork · error · PluginArchRouteFailure
connector_mapping_not_found
connector_mapping_not_found
Error message
Connector mapping not found.
What it means
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.
Source
Thrown at ee/apps/den-api/src/routes/org/plugin-system/store.ts:4214
connectorType: target.connectorType,
createdAt: new Date(),
id: createDenTypeId("connectorMapping"),
mappingConfigJson: input.config ?? null,
mappingKind: input.mappingKind,
objectType: input.objectType,
organizationId: input.context.organizationContext.organization.id,
pluginId: input.pluginId ?? null,
remoteId: null,
selector: input.selector.trim(),
updatedAt: new Date(),
}
await db.insert(ConnectorMappingTable).values(row)
return serializeConnectorMapping(row)
}
export async function updateConnectorMapping(input: { autoAddToPlugin?: boolean; config?: Record<string, unknown>; connectorMappingId: ConnectorMappingId; context: PluginArchActorContext; objectType?: ConnectorMappingRow["objectType"]; pluginId?: PluginId | null; selector?: string }) {
const mapping = await getConnectorMappingRow(input.context.organizationContext.organization.id, input.connectorMappingId)
if (!mapping) throw new PluginArchRouteFailure(404, "connector_mapping_not_found", "Connector mapping not found.")
await ensureEditableConnectorInstance(input.context, mapping.connectorInstanceId)
if (input.pluginId) {
await ensureEditablePlugin(input.context, input.pluginId)
}
await db.update(ConnectorMappingTable).set({
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(),
}).where(eq(ConnectorMappingTable.id, mapping.id))
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() })
}
export async function deleteConnectorMapping(input: { connectorMappingId: ConnectorMappingId; context: PluginArchActorContext }) {
const mapping = await getConnectorMappingRow(input.context.organizationContext.organization.id, input.connectorMappingId)
if (!mapping) throw new PluginArchRouteFailure(404, "connector_mapping_not_found", "Connector mapping not found.")View on GitHub (pinned to 2b7df46e8a)
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
Example fix
// before
await updateConnectorMapping({ connectorMappingId: id, context, config: newConfig })
// after
try {
await updateConnectorMapping({ connectorMappingId: id, context, config: newConfig })
} catch (e) {
if (isPluginArchRouteFailure(e) && e.code === "connector_mapping_not_found") {
await refreshMappings() // stale id, reload
} else throw e
} Defensive patterns
Strategy: try-catch
Validate before calling
const mappings = await listConnectorMappings({ connectorTargetId: targetId, context })
if (!mappings.some((m) => m.id === connectorMappingId)) throw new Error("mapping no longer exists — refresh") Type guard
function isConnectorMappingNotFound(e: unknown): boolean {
return e instanceof PluginArchRouteFailure && e.code === "connector_mapping_not_found"
} Try / catch
try {
await updateConnectorMapping({ connectorMappingId, context, config })
} catch (e) {
if (isConnectorMappingNotFound(e)) { await refreshMappingList(); return }
throw e
} Prevention
- 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
When it happens
Trigger: Calling updateConnectorMapping with a connectorMappingId that was deleted (e.g. by deleteConnectorMapping), never existed, is mistyped, or belongs to another organization.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/11ab3dd6dd24f635.
Report an issue: GitHub.