How to Troubleshoot Common Semantic Model Configuration Errors in Dat

Validate your Dat semantic models through the pre-build, model-level, and runtime checks to catch duplicate names, invalid SQL syntax, and database-specific errors before deployment.

Dat’s semantic model configuration is validated at multiple layers during project build and runtime. Understanding where these checks occur—inside PreBuildValidator and SemanticModelUtil—allows you to quickly pinpoint and resolve configuration errors. This guide walks you through the validation pipeline, common error patterns, and a systematic troubleshooting workflow based on the junjiem/dat source code.

Understanding the Validation Pipeline

Dat validates semantic models through three distinct phases: project pre-build, model-level static analysis, and SQL generation with runtime execution. Each phase catches different categories of errors.

Project Pre-Build Validation

During the build phase, ai.dat.boot.PreBuildValidator.validateSemanticModelSqls (lines 29-41 in dat-sdk/src/main/java/ai/dat/boot/PreBuildValidator.java) parses the generated SQL and runs a lightweight validation query (WITH … SELECT 1) against the target database. This ensures the model compiles and that database connectivity is functional.

Model-Level Validation

The ai.dat.core.utils.SemanticModelUtil class provides static validation methods used throughout the codebase. validateSemanticModels and validateSemanticModel (lines 34-60 in dat-core/src/main/java/ai/dat/core/utils/SemanticModelUtil.java) check for duplicate model names, verify the model string starts with SELECT, and forbid trailing semicolons.

SQL Generation and Runtime Execution

When generating the final query, SemanticModelUtil.semanticModelSql (lines 93-141) builds the SQL by concatenating entity, dimension, and measure expressions, then parses the user-provided model portion with Calcite. Runtime errors surface when DatabaseAdapter.executeQuery (called from PreBuildValidator at lines 66-71) executes the generated SQL against the configured database.

Common Semantic Model Configuration Errors and Solutions

Most configuration errors fall into six categories, each with distinct symptoms and resolution steps.

Duplicate Model Names

Symptom: IllegalArgumentException: There are duplicate semantic model names: …

Root Cause: The validateSemanticModels method uses a groupingBy operation to collect duplicate names across all models defined in your YAML files.

Solution: Ensure each model’s name field is unique within the project scope (typically under agents[].semantic_models). Run a quick check with:

grep -R "name:" src/**/*.yaml | sort | uniq -c | grep -v " 1 "

Invalid SELECT Statement Format

Symptom: IllegalArgumentException: The model of the semantic model 'X' must be a SELECT statement

Root Cause: validateSemanticModel checks sql.trim().toUpperCase().startsWith("SELECT"). Any CTEs without a leading SELECT or non-query statements fail this check.

Solution: Prepend SELECT to the model definition or wrap subqueries in a SELECT … FROM (…) structure. Ensure no leading whitespace or comments precede the SELECT keyword.

Trailing Semicolon Errors

Symptom: IllegalArgumentException: … cannot contain ';'

Root Cause: A regex .*\\s*;\\s*$ in validateSemanticModel detects trailing semicolons that could break SQL concatenation during generation.

Solution: Remove any trailing ; from the model string in your YAML configuration. The parser automatically handles statement termination.

Calcite Parse Failures

Symptom: SqlParseException: …

Root Cause: semanticModelSql parses each entity.expr, dimension.expr, and measure.expr using SqlParserWrapper (Calcite). Invalid SQL syntax or dialect-specific functions trigger this exception.

Solution: Verify each expression is valid SQL for your target dialect (e.g., PostgreSQL). Test expressions individually in your database client before adding them to the model. Check that function names and syntax match the adapter’s capabilities.

Database Execution Errors

Symptom: SQLException: column … does not exist or similar database-specific messages

Root Cause: PreBuildValidator.validateSemanticModelSqls executes a validation query (SELECT 1 FROM <CTE> WHERE 1=0) against the actual database. Missing tables, columns, or unsupported functions surface here.

Solution: Confirm all referenced columns and tables exist in the underlying source tables. Verify that any time-granularity functions are supported by your configured adapter. Check database connectivity and credentials in the db.provider configuration.

Time-Granularity Misconfiguration

Symptom: Errors like "Unsupported time granularity"

Root Cause: semanticModelSql calls semanticAdapter.applyTimeGranularity to handle dimension.type=TIME configurations. Invalid typeParams.timeGranularity values cause failures.

Solution: Ensure the dimension.type is set to TIME and that typeParams.timeGranularity matches a supported value (e.g., day, hour, minute). Consult your specific SemanticAdapter implementation for supported granularities.

Step-by-Step Troubleshooting Workflow

Follow this systematic approach to isolate and resolve semantic model configuration errors:

  1. Run a dry build – Execute dat build (or the Maven compile step) to trigger PreBuildValidator. Capture the full exception stack trace.

  2. Locate the offending model – The error message includes the model name; open the corresponding YAML file under agents[].semantic_models.

  3. Inspect the model field – Verify it starts with SELECT and contains no trailing semicolons.

  4. Validate each expression – For every entity, dimension, or measure, copy the expr into a SQL client using the same dialect and execute it independently.

  5. Check for duplicate names – Run a quick grep to identify naming collisions: grep -R "name:" src/**/*.yaml | sort | uniq -c | grep -v " 1 ".

  6. Confirm DB connectivity – Ensure the db.provider configuration points to a reachable database with valid credentials.

  7. Rerun the build – After fixes, rebuild the project. Successful completion indicates the semantic model is valid.

Programmatic Validation Examples

You can also validate models programmatically using Dat’s utility classes.

Detecting Duplicate Model Names

List<SemanticModel> models = // loaded from YAML
SemanticModelUtil.validateSemanticModels(models);   
// throws IllegalArgumentException if duplicates exist

Stack trace indicator: There are duplicate semantic model names: foo, bar → rename duplicated entries.

Manually Testing Generated SQL

// Using a PostgreSQL adapter
SemanticAdapter pgAdapter = new PostgreSqlSemanticAdapter();
SemanticModel model = // loaded from YAML
String sql = SemanticModelUtil.semanticModelSql(pgAdapter, model);
System.out.println(sql);      // review the full CTE-wrapped query

Copy the printed SQL into psql or your DB client. Execution failures indicate problems in expressions or underlying tables.

Using PreBuildValidator in Tests

PreBuildValidator validator = new PreBuildValidator();
try {
    validator.validate(project);   // triggers all semantic model checks
} catch (ValidationException e) {
    System.err.println(e.getMessage()); // detailed list of offending models
}

Summary

  • Validation occurs in three phases: pre-build (PreBuildValidator), model-level (SemanticModelUtil), and runtime SQL execution.
  • Common errors include: duplicate model names, missing SELECT keywords, trailing semicolons, Calcite parse failures, and database execution errors.
  • Key files to inspect: SemanticModelUtil.java for static validation logic and PreBuildValidator.java for build-time SQL verification.
  • Systematic troubleshooting: Run a dry build, inspect the model field format, validate individual expressions in your SQL client, and confirm database connectivity.

Frequently Asked Questions

How do I fix "duplicate semantic model names" errors?

This error originates in SemanticModelUtil.validateSemanticModels when the groupingBy operation detects identical name values across your YAML configurations. To resolve, ensure each model has a unique name field within the project scope, typically defined under agents[].semantic_models. Use grep to scan for duplicates across your YAML files.

Why does my model fail with "must be a SELECT statement"?

The validateSemanticModel method in SemanticModelUtil.java enforces that every model string must start with SELECT (case-insensitive after trimming). This check prevents injection of non-query statements. If your model uses CTEs or subqueries, ensure the outermost statement is a SELECT, or wrap the entire logic in SELECT * FROM (...).

How can I validate semantic models without running a full build?

You can programmatically validate models using SemanticModelUtil.validateSemanticModels(List<SemanticModel>) for static checks, or instantiate PreBuildValidator to execute the full validation pipeline including SQL generation and database connectivity tests. This approach is useful for unit testing or CI/CD pipelines where you want fast feedback on configuration changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →