{"record":{"id":"4e18a5c3ff01ba0a","repo":"dbt-labs/dbt-core","slug":"schema-not-found-for-canonical-fqn","errorCode":null,"errorMessage":"Schema not found for canonical FQN: {}","messagePattern":"Schema not found for canonical FQN: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-df-providers/src/delayed_table.rs","lineNumber":78,"sourceCode":"            schema_store: schema_cache,\n            data_store,\n            data_provider: OnceLock::new(),\n        }\n    }\n}\n\n#[async_trait::async_trait]\nimpl TableProvider for DelayedDataTableProvider {\n    fn as_any(&self) -> &dyn Any {\n        self\n    }\n\n    fn schema(&self) -> Arc<arrow_schema::Schema> {\n        let schema_entry = self\n            .schema_store\n            .get_schema(&self.canonical_fqn)\n            .unwrap_or_else(|| {\n                panic!(\"Schema not found for canonical FQN: {}\", self.canonical_fqn);\n            });\n        schema_entry.inner().clone()\n    }\n\n    /// Ensures the physical data provider exists before delegating to it.\n    async fn scan(\n        &self,\n        state: &dyn Session,\n        projection: Option<&Vec<usize>>,\n        filters: &[Expr],\n        limit: Option<usize>,\n    ) -> Result<Arc<dyn datafusion::physical_plan::ExecutionPlan>, DataFusionError> {\n        // Set the data provider here...\n        let schema = self.schema();\n        let provider = if let Some(provider) = self.data_provider.get() {\n            provider.clone()\n        } else {\n            let provider = make_listing_table_provider(","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-df-providers/src/delayed_table.rs#L60-L96","documentation":"DelayedTableProvider caches Arrow schemas keyed by canonical fully-qualified table name in a schema_store. When `schema()` is called, the entry for this table's canonical FQN must already have been populated by an earlier registration step; if it is absent, the code panics rather than returning a wrong or empty schema. This is an internal invariant: a schema should never be requested before it is registered.","triggerScenarios":"Calling `schema()` (directly or via `scan()`) on a DelayedTableProvider whose canonical_fqn was never inserted into schema_store — e.g. the registration/planning step that populates the store was skipped, the FQN normalization differs between writer and reader, or a race dropped the entry before read.","commonSituations":"Querying a dbt model's table relation before the model finished building; a plan referencing a relation whose schema registration failed earlier in the pipeline; case- or catalog-qualification mismatches producing a canonical FQN that doesn't equal the key used at registration.","solutions":["Ensure the pipeline registers the schema via schema_store.get/insert with the exact same canonical FQN before any schema()/scan() call.","Log and compare the canonical_fqn used at registration time against the one used at lookup to find qualification mismatches.","Verify the upstream model/table actually completed building before querying the delayed provider.","Replace the panic with a fallible schema() returning Result so callers can surface 'schema not yet available' cleanly."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before requesting the schema, verify registration happened\nif schema_store.get_schema(&canonical_fqn).is_none() {\n    return Err(anyhow!(\"schema for {} not yet registered\", canonical_fqn));\n}","typeGuard":null,"tryCatchPattern":"// use a fallible accessor instead of the panicking schema()\nmatch provider.try_schema() {\n    Ok(schema) => schema,\n    Err(e) => bail!(\"delayed table {} has no registered schema: {}\", fqn, e),\n}","preventionTips":["Always register the schema in schema_store under the exact canonical FQN before planning/scan.","Share one FQN-normalization helper so writer and reader keys cannot diverge.","Await model completion before constructing providers for its relation.","Prefer returning Result over panic in library code so missing schemas surface as user-facing errors."],"tags":["rust","panic","schema","dataframe","internal"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}