multica-ai/multica · error

attribution strict-constraint pre-198 hook: %w

Error message

attribution strict-constraint pre-198 hook: %w

What it means

The pre-198 hook that backfills accountable_user_id from originator_user_id (attributionbackfill.Hook, GH #5544 / MUL-4897) failed, aborting the run before the strict attribution constraint migration executes. Without this hook, self-hosted databases that never ran the out-of-band backfill would fail migration 198's validation outright.

Source

Thrown at server/cmd/migrate/main.go:221

			"watermark_stamped", res.WatermarkStamped)
		return nil
	}
	slog.Info("task_usage hourly rollup hook: backfill complete",
		"slices", res.SlicesProcessed,
		"rows_touched", res.RowsTouched,
		"from", res.From.Format("2006-01-02T15:04:05Z07:00"),
		"to", res.To.Format("2006-01-02T15:04:05Z07:00"))
	return nil
}

// runAttributionStrictHook backfills accountable_user_id from
// originator_user_id before migration 198 validates the strict attribution
// constraint, so self-hosted upgrades that never ran the out-of-band
// backfill recover automatically (GH #5544 / MUL-4897).
func runAttributionStrictHook(ctx context.Context, pool *pgxpool.Pool) error {
	res, err := attributionbackfill.Hook(ctx, pool, attributionbackfill.HookOptions{})
	if err != nil {
		return fmt.Errorf("attribution strict-constraint pre-198 hook: %w", err)
	}
	slog.Info("attribution backfill hook: complete",
		"rows_backfilled", res.RowsBackfilled,
		"batches", res.Batches,
		"mismatch_normalized", res.MismatchNormalized)
	return nil
}

// migrationAdvisoryLockKey is the int64 identifier used with Postgres
// pg_advisory_lock to serialize the migration loop across concurrent
// runners (multi-replica backend Deployment, scale-up, or a manual
// `migrate up` overlapping with pod startup). The exact value is
// arbitrary — it just needs to be stable across every process that runs
// migrations against the same database. See GitHub multica-ai/multica#3647.
const migrationAdvisoryLockKey int64 = 7244554146635925501

// defaultSchemaMigrationsTable is the unqualified name of the bookkeeping
// table that tracks which migrations have been applied. Tests override

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Inspect the wrapped error: 42P01/42703 mean schema drift — apply/repair earlier migrations first
  2. For timeouts on large tables, raise statement_timeout and ensure no long transactions hold locks on tasks
  3. Re-run `migrate up` — the hook is batched and resumable, and the version is only recorded after success
Defensive patterns

Strategy: retry

Try / catch

res, err := attributionbackfill.Hook(ctx, pool, attributionbackfill.HookOptions{})
if err != nil {
    return fmt.Errorf("attribution strict-constraint pre-198 hook: %w", err)
}

Prevention

When it happens

Trigger: The tasks/attribution tables or columns referenced by the backfill query are missing or have unexpected types; statement/lock timeouts while batch-updating a large tasks table; connection loss mid-batch; cancelled context.

Common situations: Upgrading an old self-hosted instance with many rows where accountable_user_id is NULL; a partially applied earlier migration leaving schema drift.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/31515487108834a3. Report an issue: GitHub.