Troubleshooting
View function logs
from cognite.client import CogniteClient
client = CogniteClient()
calls = client.functions.calls.list(
function_external_id="data-quality-validation",
limit=10,
)
logs = client.functions.calls.get_logs(call_id=calls[0].id)
print(logs)
Check workflow execution status
executions = client.workflows.executions.list(
workflow_external_id="dq-shacl-equipment",
limit=10,
)
for execution in executions:
print(f"Status: {execution.status}, Started: {execution.started_at}")
Workflow not triggering on data changes
Symptoms: Instance changes in DMS don't start the validation workflow.
Check:
- Retrieve the trigger and verify it is active:
- Verify the instance space in the trigger filter matches the space where data changes occur.
- Confirm the workflow version in the trigger matches the deployed workflow version.
- If you deployed with
--skip-trigger, redeploy without that flag.
Uniqueness workflow not deployed
Symptoms: View has dqs:unique in SHACL but no dq-{view}-uniqueness workflow in CDF.
Check:
- Confirm the constraint's
sh:targetClassmatches the view's data model class (deploy scans SHACL for the view'sexternal_id). - For DataProduct/RuleSet mode, verify
RuleSetClient.get_version()returns TTL with the constraint (deploy fetches RuleSet content at deploy time). - Check deploy logs for
Skipping uniqueness workflow ... no SHACL uniqueness constraints foundor SHACL parse warnings. - Ensure
uniqueness_cronis not set tonullin view YAML (that disables the scheduled workflow).
Uniqueness not running after sync
Expected behaviour. Sync-cursor (instance_sync_cursor) runs incremental pyshacl only. Global uniqueness runs on the scheduled dq-{view}-uniqueness workflow, not after each sync completion.
To run on demand: call_validate_shacl() with validation_type: shacl or trigger the uniqueness workflow manually.
Uniqueness workflow runs but no records appear
Symptoms: The scheduled uniqueness workflow succeeds, SHACL discovery finds dqs:uniquenessConstraint, and the investigation script reports duplicates, but the Records stream has no uniqueness rows.
Check:
- Confirm function logs include
job_run_idon theAGGREGATE UNIQUENESS VALIDATIONbanner. Scheduled uniqueness mintsjob_{view}_uniqueness_{epoch}when the cron trigger omitsjob_run_id.MISSING_JOB_RUN_IDnow means the low-levelaggregate_uniquenessexecutor was invoked without an id (the function call should be Failed). - Confirm logs include
[aggregate_uniqueness] outcome ... recordsPosted=.... Absence ofPosting batchmeans posting was never attempted. - Read the function return JSON for
globalRuleResults[].result(recordsPosted,violatingBuckets,errorCode). Do not rely on the short log banner alone, especially whenverbose: false. - Filter Records by
ruleSetId/validationType(single_violationorgroup_violation). Uniqueness records setdimensionsto["Uniqueness"](or thedq:dimensionon the NodeShape).dq:dimensionis not required for uniqueness to run. After this release, uniqueness rows no longer use nesteddimension: Consistency— update dashboard filters that keyed uniqueness findings on Consistency. - Confirm the uniqueness workflow is the scheduled
dq-{view}-uniquenesspath (validation_type: shacl). Directaggregate_uniquenessinvokes still require an explicitjob_run_id.
Uniqueness duplicates still exist but few/no new failure records
Often expected behaviour. Uniqueness now suppresses repeated failure writes for unchanged instances.
Suppression rule:
- If latest existing failed record for a
focusNodehasrecord.lastUpdatedTime >= instance.lastUpdatedTime, runtime suppresses writing a new failure record.
Check:
- Inspect uniqueness run output fields:
violatingInstanceCountrecordsPostedrecordsSuppressed- If
recordsSuppressedis high andrecordsPostedis low, dedupe is likely working as intended. - Update an affected instance and rerun uniqueness — a new failure record should appear if the violation remains.
From validation records:
- Check grouped uniqueness records for typed overflow signals:
groupViolationType = "global_overflow"(run-level overflow)groupViolationType = "value_overflow"(single-value overflow)- If either overflow type is present, this run hit a guardrail and more duplicate groups may still remain.
- Fix the reported duplicates and rerun uniqueness until overflow records disappear.
Note:
- If no new records are written (for example due to dedupe suppression), users may not see a new overflow record for that run.
- In that case, ask an operator to confirm run-level warnings from workflow/function output.
Grouped uniqueness records are explicitly marked with:
validationType = "group_violation"groupViolationType = "global_overflow" | "value_overflow" | "pass"
"Failed to load SHACL rules"
Symptoms: Function logs show an error loading rules.
Instance, time series, or uniqueness validation
Check:
- Verify
ruleset_referencesis present on the workflow trigger input or function payload. - Confirm each referenced RuleSet version exists and contains Turtle rules.
- After upgrading to 0.4.0, redeploy workflows — handlers no longer load SHACL from
shacl_rules_file_external_id. - Validate Turtle syntax locally:
RAW table validation
Check:
- Verify the SHACL file exists in CDF Files with the expected external ID.
- Confirm the external ID in the RAW table config (
shacl_rules.external_id) matches the file. - Verify the file is in the correct CDF dataset (
shacl_rules.dataset_external_idinsettings.yaml).
"No instances to validate"
Symptoms: Validation completes with zero instances processed.
Check:
- Confirm the DMS filter in the view config or time series config is correct.
- Verify instances exist in the configured space.
- Ensure the view external ID and version match the actual view in CDF.
Zero violations when you expect some
Symptoms: Validation runs but produces no violations for a rule you expect to fire.
Check:
- The
sh:targetClassin the SHACL rule targets a concrete view type, not a CDF interface.
Interfaces (e.g.MMSINumber) are not used asrdf:typein the RDF graph — concrete view types (e.g.NavigationAid) are. A shape targeting an interface silently matches nothing. - Run with
print_output=Trueandverbose=Trueto see per-instance output and zero-instance class warnings. - Check
auto_load_depth— if the rule uses properties from referenced instances, depth0won't load them.
See SHACL rules and CDF data models for details.
Function dependency errors
"ModuleNotFoundError: No module named 'cognite_data_quality'"
The function was deployed before the package was published to PyPI, or is pinned to an old version.
- Publish the latest package:
python -m build && twine upload dist/* - Force redeploy:
python scripts/deploy_infrastructure.py --env <env> --force
RAW table validation issues
"RAW table not found"
- Verify the RAW database and table names in the config match what exists in CDF.
- Confirm the service principal has read access to the RAW table.
"No rows updated since last run"
Normal for incremental validation when no changes occurred. Check RawValidationState in the dataQuality DMS space for last_processed_timestamp to confirm.
Cursor state not saving
- Ensure the
dataQualityspace exists in CDF. - Verify the service principal has write access to the
dataQualityspace. - Run
deploy_validation_infrastructure()to ensure state containers (FunctionValidationState,RawValidationState, etc.) exist.
Records API returns no results
Symptoms: Filter queries return empty items.
Check:
- Confirm
client.config.headers["cdf-version"] = "alpha"is set before the request. - Verify the stream ID in the query matches
records.stream_idinsettings.yaml. - Check the time range — Records API filters use milliseconds since epoch. Widen
lastUpdatedTimeto confirm records exist.
Sync-cursor validation issues
Sync lock / data_quality_space errors
Symptoms: Sync-cursor fails immediately with sync lock errors, for example space must not be null.
Check:
- Omit
data_quality_spacefrom trigger/workflow input to use the defaultdataQuality, or pass a non-empty space string. The sync-cursor handler normalizes null/empty todataQualityviaresolve_data_quality_space()— explicitnullin upstream workflow refs can still break other handlers if not stripped. - Confirm the
dataQualityspace exists and the function principal can read/write DMS state there. - See Sync-cursor and historic orchestration.
Full backlog replay after historic
Symptoms: Sync-cursor processes tens of thousands of instances after historic completed; steady "Sync lock held" logs.
Cause: Stale sync cursor preserved across historic handoff (fixed in 0.4.1).
Fix: Upgrade to 0.4.1+, re-run historic orchestration for the view, or manually reset sync cursor state after confirming historic completed.
No sync trigger after deploy
Expected: Deploy does not create DMS instance sync triggers. The historic orchestrator creates them in Step 3.
Fix: Run deploy_validation_pipeline() or wait for version-change historic enqueue via data_product_sync.
Note: Sync trigger creation can fail inside the orchestrator (timeout, secrets). Historic partitions may still complete; check orchestrator logs for Sync trigger: not created and sync_trigger_error.
job_run_id and historic runs
Symptoms: Missing job_run_id error from sync-cursor or the low-level aggregate uniqueness executor.
Fix: For instance sync / historic, pass explicit job_run_id in workflow trigger input (format: job_{view}_{epoch_seconds}). Scheduled uniqueness mints job_{view}_uniqueness_{epoch} when omitted. Direct aggregate_uniqueness calls still need an explicit id.
Symptoms: Dashboard shows no records for a historic run you triggered.
Check:
- Filter on
jobRunIdusing the orchestrator id (job_*), not legacyhq_*queue ids. - Confirm orchestrator and partitions used the same
job_run_idfromdeploy_validation_pipeline().
See Invoke → job_run_id.
Historic validation processes fewer instances than expected
Symptoms: Auto-enqueued historic run validates far fewer instances than expected, or validates instances outside the intended site space.
Check:
HistoricJobQueuerebuilds orchestrator input from the live DataProduct API at job start (instanceSpaces.read), then overlaysViewConfigState(including YAMLinstance_spaceswhen stored).- Compare orchestrator payload
instance_spacesin logs with both the DataProduct view definition and theViewConfigStatenode. - If YAML
instance_spacesis narrower than DataProductinstanceSpaces.read(for example a single site space on a multi-site DataProduct), the YAML override should win afterdeploy_validation_infrastructure(). Redeploy infrastructure if the override was added after the last ViewConfigState upsert. - If no override is stored, the live DataProduct
instanceSpaces.readlist is used.
Edge existence issues
Symptoms: Edge rules deploy but no baseline coverage after version change.
Check:
- Confirm historic orchestrator triggered Step 3b (
edge_existence_baselinecall ids in orchestrator logs /OrchestrationState.edge_baseline_call_ids). - Baseline runs asynchronously — orchestrator completion does not mean baseline finished. Check baseline Function calls and records.
- On baseline timeout, re-invoke
edge_existence_baselinemanually with the samejob_run_id(no orchestrator auto-resume). - For unchanged DP version needing workflow/trigger refresh: bump DataProduct version or run
data_product_syncwithforce: true. - For unchanged version needing full re-scan without historic: invoke baseline manually (
force_rerun).
Symptoms: Incremental edge validation never fires.
Check:
- Verify two modeling triggers per rule (node + edge) on
{dp_wf}-edge-existence. - Confirm trigger
sync_kindrouting — node changes evaluate focus nodes; edge changes resolve focus from edge endpoints.
Symptoms: False failures using sh:minCount on MultiEdgeConnection property paths.
Fix: Use dqs:edgeExistenceConstraint instead — see Edge existence.
Empty dimensions on validation records
Symptoms: Rules include dq:dimension but dimensions is empty on records.
Check:
@prefix dq:must behttp://purl.org/cognite/cdf_dq/DataQuality/(nothttp://example.org/dataquality/).- Redeploy CDF Function with
cognite-data-quality≥ 0.4.3. - Function logs:
Dimension lookup: N named shapes, M property paths— if both zero, namespace mismatch.