zitadel/zitadel · critical

unable to create projections: %w

Error message

unable to create projections: %w

What it means

In Setup (cmd/setup/setup.go), projection.Create initializes the projection tables and their handlers in the database. When that fails, ZITADEL wraps the error with "unable to create projections". This means the database could not create the projection schemas/tables or start the projection handlers, so no migration steps run afterwards.

Source

Thrown at cmd/setup/setup.go:264

	steps.s61IDPTemplate6SAMLSignatureAlgorithm = &IDPTemplate6SAMLSignatureAlgorithm{dbClient: dbClient}
	steps.s62HTTPProviderAddSigningKey = &HTTPProviderAddSigningKey{dbClient: dbClient}
	steps.s63AlterResourceCounts = &AlterResourceCounts{dbClient: dbClient}
	steps.s64ChangePushPosition = &ChangePushPosition{dbClient: dbClient}
	steps.s65FixUserMetadata5Index = &FixUserMetadata5Index{dbClient: dbClient}
	steps.s66SessionRecoveryCodeCheckedAt = &SessionRecoveryCodeCheckedAt{dbClient: dbClient}
	steps.s67SyncMemberRoleFields = &SyncMemberRoleFields{dbClient: dbClient}
	steps.s68TargetAddPayloadTypeColumn = &TargetAddPayloadTypeColumn{dbClient: dbClient}
	steps.s69CacheTablesLogged = &CacheTablesLogged{dbClient: dbClient}
	steps.s70AddEventStoreCommandEnforceOwner = &AddEventStoreCommandEnforceOwnerColumn{dbClient: dbClient}
	steps.s71JWTProvideAddAudienceColumn = &JWTProvideAddAudienceColumn{dbClient: dbClient}
	steps.s72AddColumnsToLoginNamesView = &AddColumnsToLoginNamesView{dbClient: dbClient}
	steps.s73FixUserGrantRoles = &FixUserGrantRoles{eventstore: eventstoreClient}
	steps.s74Apps7OIDCConfigsAddRegistrationToken = &Apps7OIDCConfigsAddRegistrationToken{dbClient: dbClient}
	steps.s75Apps7OIDCConfigsAddAppLinkConfig = &Apps7OIDCConfigsAddAppLinkConfig{dbClient: dbClient}

	err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil, nil)
	if err != nil {
		return fmt.Errorf("unable to create projections: %w", err)
	}

	for _, step := range []migration.Migration{
		steps.s14NewEventsTable,
		steps.s40InitPushFunc,
		steps.s1ProjectionTable,
		steps.s2AssetsTable,
		steps.s28AddFieldTable,
		steps.s31AddAggregateIndexToFields,
		steps.s46InitPermissionFunctions,
		steps.FirstInstance,
		steps.s5LastFailed,
		steps.s6OwnerRemoveColumns,
		steps.s7LogstoreTables,
		steps.s8AuthTokens,
		steps.s12AddOTPColumns,
		steps.s13FixQuotaProjection,
		steps.s15CurrentStates,

View on GitHub (pinned to 13948f2bcd)

Solutions

  1. Inspect the wrapped error (%w): if it's connection refused/auth failed, fix the database DSN and credentials in your config.
  2. Grant the configured database user CREATE privileges on the target schema/database.
  3. Verify the database is reachable from where setup runs (psql with the same DSN).
  4. If a previous setup failed midway, clean up partially created projection tables or restore a clean schema, then re-run setup.

Example fix

// before (config.yaml) — wrong port
Database:
  postgres:
    Host: db
    Port: 5433
// after
Database:
  postgres:
    Host: db
    Port: 5432
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight DB check before running setup:
cmd := exec.Command("psql", dsn, "-c", "SELECT 1")
if err := cmd.Run(); err != nil {
    return fmt.Errorf("database not reachable/authorized: %w", err)
}

Try / catch

err := projection.Create(ctx, dbClient, esClient, config.Projections, nil, nil, nil)
if err != nil {
    // retry transient network failures with backoff; surface otherwise
    return fmt.Errorf("unable to create projections: %w", err)
}

Prevention

When it happens

Trigger: projection.Create returns an error during `zitadel setup`: the database is unreachable, the user lacks CREATE privileges, a projection table already exists in an incompatible state, or an internal projection handler query fails.

Common situations: Wrong database host/port/credentials in config (connection refused or auth failure); Postgres user without DDL rights on the schema; partially-failed previous setup leaving half-created projection tables; network/firewall blocking the DB during a Kubernetes setup job.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of zitadel/zitadel@13948f2bcd (2026-09-06). Data as JSON: /api/errors/fd96c83aaa7ddcfe. Report an issue: GitHub.