{"record":{"id":"63851bb69342a6f3","repo":"multica-ai/multica","slug":"stamp-watermark-w","errorCode":null,"errorMessage":"stamp watermark: %w","messagePattern":"stamp watermark: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/backfill_task_usage_hourly/main.go","lineNumber":207,"sourceCode":"\tif err := stampWatermark(context.Background(), pool); err != nil {\n\t\treturn err\n\t}\n\tslog.Info(\"backfill complete\", \"total_rows_touched\", totalRows)\n\treturn nil\n}\n\n// stampWatermark moves the hourly rollup state's watermark to\n// `now() - 5 min`, mirroring the cron entry's upper bound. The next\n// scheduled tick therefore picks up only events newer than the\n// backfill horizon and does not redo work the backfill already did.\nfunc stampWatermark(ctx context.Context, pool *pgxpool.Pool) error {\n\ttag, err := pool.Exec(ctx, `\n\t\tUPDATE task_usage_hourly_rollup_state\n\t\t   SET watermark_at = now() - INTERVAL '5 minutes'\n\t\t WHERE id = 1\n\t`)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"stamp watermark: %w\", err)\n\t}\n\tif tag.RowsAffected() == 0 {\n\t\tslog.Warn(\"no rollup state row to stamp; was the task_usage_hourly schema migration applied?\")\n\t\treturn nil\n\t}\n\tfmt.Println(\"watermark stamped to now() - 5 minutes\")\n\treturn nil\n}\n\nfunc monthFloor(t time.Time) time.Time {\n\treturn time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)\n}\n","sourceCodeStart":189,"sourceCodeEnd":220,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/backfill_task_usage_hourly/main.go#L189-L220","documentation":"The final UPDATE task_usage_hourly_rollup_state SET watermark_at = now() - INTERVAL '5 minutes' WHERE id = 1 failed at the SQL level. This stamps the cron watermark so scheduled ticks only process events newer than the backfill horizon. A related but distinct case — RowsAffected()==0 — is handled gracefully with a warning (no rollup state row), so an actual error here is a connection/cancellation/permission problem.","triggerScenarios":"task_usage_hourly_rollup_state table missing (migration 103+ not applied) yields 42P01; ctx cancelled right at the finish; permissions revoked on the table.","commonSituations":"SIGINT arriving between the last slice and the stamp; running against a partially migrated database. Note: if this fails after slices completed, the data IS rolled up but the watermark is stale — the cron tick will redo recent windows (idempotent) rather than lose data.","solutions":["Re-run the backfill: slices are idempotent and the stamp will retry","Confirm task_usage_hourly_rollup_state exists (migration applied); if the 'no rollup state row' warning appears instead, apply the schema migration that creates it","If it recurs, check the wrapped error for auth/permission issues on the table"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"var stateExists bool\npool.QueryRow(ctx, `SELECT to_regclass('task_usage_hourly_rollup_state') IS NOT NULL`).Scan(&stateExists)","typeGuard":null,"tryCatchPattern":"tag, err := pool.Exec(ctx, `UPDATE task_usage_hourly_rollup_state SET watermark_at = now() - INTERVAL '5 minutes' WHERE id = 1`)\nif err != nil {\n    return fmt.Errorf(\"stamp watermark: %w\", err)\n}","preventionTips":["Re-run the backfill on stamp failure — data is safe, only the watermark lags","Remember RowsAffected()==0 is a warning path, not an error: it means the migration was never applied"],"tags":["go","postgres","backfill","watermark","sql"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}