{"record":{"id":"5a0f717d53c915e1","repo":"different-ai/openwork","slug":"invalid-github-materialization-context","errorCode":"invalid_github_materialization_context","errorMessage":"GitHub connector target is missing required materialization context.","messagePattern":"GitHub connector target is missing required materialization context\\.","errorType":"http","errorClass":"PluginArchRouteFailure","httpStatus":409,"severity":"error","filePath":"ee/apps/den-api/src/routes/org/plugin-system/store.ts","lineNumber":6615,"sourceCode":"async function materializeGithubImportPlans(input: {\n  connectorInstance: ReturnType<typeof serializeConnectorInstance>\n  connectorSyncEventId?: ConnectorSyncEventId\n  connectorTarget: ReturnType<typeof serializeConnectorTarget>\n  context: PluginArchActorContext\n  importPlans: Array<{ fileShaByPath?: Record<string, string>; mapping: ReturnType<typeof serializeConnectorMapping>; paths: string[] }>\n  sourceRevisionRef: string\n}) {\n  const config = githubConnectorAppConfig()\n  const targetConfig = input.connectorTarget.targetConfigJson && typeof input.connectorTarget.targetConfigJson === \"object\"\n    ? input.connectorTarget.targetConfigJson as Record<string, unknown>\n    : {}\n  const branch = typeof targetConfig.branch === \"string\" ? targetConfig.branch : input.connectorTarget.externalTargetRef ?? \"\"\n  const installationId = typeof input.connectorInstance.instanceConfigJson === \"object\" && input.connectorInstance.instanceConfigJson && typeof (input.connectorInstance.instanceConfigJson as Record<string, unknown>).installationId === \"number\"\n    ? (input.connectorInstance.instanceConfigJson as Record<string, unknown>).installationId as number\n    : null\n  const repositoryFullName = typeof targetConfig.repositoryFullName === \"string\" ? targetConfig.repositoryFullName : input.connectorTarget.remoteId\n  if (!installationId || !branch || !repositoryFullName) {\n    throw new PluginArchRouteFailure(409, \"invalid_github_materialization_context\", \"GitHub connector target is missing required materialization context.\")\n  }\n\n  const token = await getGithubInstallationAccessToken({\n    config,\n    installationId,\n  })\n  const organizationId = input.context.organizationContext.organization.id\n  const plannedFiles = input.importPlans.flatMap((plan) => plan.paths.map((path) => ({\n    mapping: plan.mapping,\n    path,\n    sourceFileRevisionRef: plan.fileShaByPath?.[path] ?? null,\n  })))\n  const existingBindings = await Promise.all(plannedFiles.map((file) => findActiveConnectorSourceBinding({\n    connectorMappingId: file.mapping.id,\n    externalLocator: file.path,\n    organizationId,\n  })))\n  const fetchResults = await fetchGithubImportFilesWithRevisionGuard({","sourceCodeStart":6597,"sourceCodeEnd":6633,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/routes/org/plugin-system/store.ts#L6597-L6633","documentation":"Thrown (409) when a GitHub connector target lacks any of the three required materialization inputs: an installationId (from the connector instance's instanceConfigJson), a branch (from targetConfig.branch or the target's externalTargetRef), or a repositoryFullName (from targetConfig.repositoryFullName or the target's remoteId). Materialization cannot proceed against GitHub without all three.","triggerScenarios":"Materializing plugin code from a GitHub connector where the GitHub App was never installed (no installationId in instanceConfigJson), the target config omits `branch`, or repositoryFullName/remoteId is empty or misconfigured.","commonSituations":"Partial connector target setup: repo selected but branch never saved; App uninstalled from the org leaving stale instance config; manual DB edits dropping remoteId; connecting a target before completing the GitHub install callback.","solutions":["Complete the GitHub App installation so instanceConfigJson contains a numeric installationId.","Set `branch` (or externalTargetRef) and `repositoryFullName` (or remoteId) on the connector target config, e.g. via updateConnectorTarget.","Re-create the connector target through the normal install flow instead of hand-editing config so all fields are populated consistently."],"exampleFix":"// before\nawait materializePlugin({ connectorTargetId }) // targetConfig = { repositoryFullName: 'org/repo' } -> no branch, no installationId\n// after\nawait updateConnectorTarget(connectorTargetId, { config: { repositoryFullName: 'org/repo', branch: 'main' } })\nawait completeGithubConnectorInstall({ installationId: 12345, state }) // populates instanceConfigJson.installationId\nawait materializePlugin({ connectorTargetId })","handlingStrategy":"validation","validationCode":"const installationId = instance.instanceConfigJson && typeof instance.instanceConfigJson === 'object' ? (instance.instanceConfigJson as Record<string, unknown>).installationId : null\nconst branch = targetConfig.branch ?? target.externalTargetRef\nconst repositoryFullName = targetConfig.repositoryFullName ?? target.remoteId\nif (!installationId || !branch || !repositoryFullName) throw new Error('GitHub materialization requires installationId, branch, and repositoryFullName')","typeGuard":"function hasGithubMaterializationContext(t: { installationId: unknown; branch: unknown; repositoryFullName: unknown }): t is { installationId: number; branch: string; repositoryFullName: string } {\n  return typeof t.installationId === 'number' && t.installationId > 0 && typeof t.branch === 'string' && t.branch.length > 0 && typeof t.repositoryFullName === 'string' && t.repositoryFullName.length > 0\n}","tryCatchPattern":"try {\n  await materializePlugin({ connectorTargetId })\n} catch (e) {\n  if (e instanceof PluginArchRouteFailure && e.code === 'invalid_github_materialization_context') {\n    await restartGithubConnectorInstallFlow() // repopulate installationId/branch/repo\n  } else throw e\n}","preventionTips":["Always complete the GitHub App install before creating targets","Validate targetConfig fields (branch, repositoryFullName) at save time","Never hand-edit connector instance/target JSON; use the API flows"],"tags":["github","configuration","connector"],"backgroundTag":"missing-materialization-context","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}