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

  1. Re-fetch the mapping list for the org to confirm the ID still exists
  2. Confirm the caller's organization context owns the mapping
  3. Handle the 404 in the UI by refreshing and discarding the stale edit
  4. 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

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.