{"record":{"id":"0eea1399b73ceb82","repo":"cube-js/cube","slug":"no-dbt-sync-sync-job-id-on-deployment-deploymen","errorCode":null,"errorMessage":"no dbt sync {sync_job_id} on deployment {deployment}. It may belong to another deployment, have aged out, or this tenant may not serve the dbt-sync endpoints yet","messagePattern":"no dbt sync (.+?) on deployment (.+?)\\. It may belong to another deployment, have aged out, or this tenant may not serve the dbt-sync endpoints yet","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/cube-cli/src/commands/dbt.rs","lineNumber":248,"sourceCode":"    api: &Client,\n    deployment: i64,\n    sync_job_id: &str,\n    timeout: Duration,\n    interval: Duration,\n) -> Result<Value> {\n    let path = format!(\"{}/{}\", base(deployment), sync_job_id);\n    // A Cell, not a plain variable: the poll closure hands back a future that\n    // borrows what it captures, and a mutable capture would make each call borrow\n    // the closure itself — which the borrow checker rejects even though the calls\n    // are strictly sequential.\n    let missing_since = std::cell::Cell::new(None::<Instant>);\n\n    wait::poll(Wait::new(\"dbt sync\", timeout, interval), || async {\n        let Some(status) = api.get_optional(&path, &Vec::new()).await? else {\n            let since = missing_since.get().unwrap_or_else(Instant::now);\n            missing_since.set(Some(since));\n            if since.elapsed() > MISSING_GRACE {\n                bail!(\n                    \"no dbt sync {sync_job_id} on deployment {deployment}. It may belong \\\n                     to another deployment, have aged out, or this tenant may not serve \\\n                     the dbt-sync endpoints yet\"\n                );\n            }\n\n            return Ok(Progress::Waiting(\"starting\".to_string()));\n        };\n        missing_since.set(None);\n\n        let state = util::status_of(&status, \"status\");\n        if state == COMPLETED || state == FAILED {\n            return Ok(Progress::Done(status));\n        }\n\n        Ok(Progress::Waiting(status_label(&status)))\n    })\n    .await","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube-cli/src/commands/dbt.rs#L230-L266","documentation":"The Cube CLI's `dbt sync --wait` / `dbt status --wait` polls the deployment's dbt-sync status endpoint for a given sync_job_id. When the endpoint returns 404 continuously for longer than MISSING_GRACE (a short grace window that tolerates a sync not being visible yet), wait_for_sync gives up and bails. It means the CLI cannot see the sync job at all — not that the sync failed.","triggerScenarios":"Running `cube dbt sync <deployment> --wait` or `cube dbt status <deployment> <sync_job_id> --wait` where GET /build/api/v1/deployments/<deployment>/dbt-sync/<sync_job_id> (approximately) returns None/404 on every poll until the grace period elapses: the sync_job_id was created on a different deployment, retention has aged it out, or the tenant's API does not implement dbt-sync endpoints.","commonSituations":"Typing a sync job ID from another deployment's output; referencing a sync older than the retention window; pointing the CLI at a Cube Cloud tenant/region that predates the dbt-sync feature; a typo'd ID or wrong deployment number in a CI script.","solutions":["Verify the sync_job_id belongs to this deployment: re-run `cube dbt sync <deployment>` and use the syncJobId it prints.","Confirm the deployment number is correct — list deployments and check you are polling the one that started the sync.","If the sync is old, check whether it aged out of retention and start a fresh sync instead.","Check with Cube support/admin whether this tenant serves the dbt-sync endpoints; if not, upgrade or use a tenant that does.","If the sync was just started, retry — a slow-to-register job is tolerated only briefly by the grace window."],"exampleFix":"// before: polling a stale ID captured from an old CI run\nlet sync_job_id = env::var(\"SYNC_JOB_ID\")?; // may be from another deployment\n// after: start the sync and capture the ID in the same run\nlet started = api.post(&base(deployment), Some(&body)).await?;\nlet sync_job_id = output::field(&started, \"syncJobId\");","handlingStrategy":"retry","validationCode":"// Confirm the job exists on the right deployment before --wait\nlet status = api.get_optional(&format!(\"{base}/{sync_job_id}\"), &query).await?;\nif status.is_none() {\n    anyhow::bail!(\"sync {sync_job_id} not found on {deployment}; re-run `cube dbt sync` to mint a fresh ID\");\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"no dbt sync\") => {\n        // start a new sync and capture its syncJobId before waiting\n    }\n    other => other?,\n}","preventionTips":["Always take sync_job_id from the same run's `dbt sync` output, never from memory or another environment's logs.","Pair `--wait` with the sync invocation itself (`dbt sync --wait`) instead of waiting on a previously recorded ID.","Confirm the deployment number in scripts via a variable set at deploy time.","Don't poll sync jobs older than your tenant's retention window."],"tags":["cli","dbt","http-404","resource-not-found","polling"],"backgroundTag":"resource-not-found","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}