Priority Level
High (Major improvement)
Is your feature request related to a problem? Please describe.
Consumers that compose many columns into one Data Designer graph cannot determine, from the public run result, which column terminally failed for each omitted seed row.
Data Designer internally knows the task column, row group, and row index when a task fails. DatasetCreationResults.task_traces can expose those fields when full async tracing is enabled, but that is a heavy per-task diagnostic mechanism and the row position is not a stable caller-provided record identity. On a partially successful run, a consumer can diff input and output IDs to discover that a row disappeared, but cannot attribute that loss to the originating column without parsing logs.
This blocks an integration in NVIDIA-NeMo/Anonymizer#237 and PR #240. Anonymizer's legacy rewrite implementation uses several Data Designer runs, so a missing row can be attributed to a stage such as replacement-map generation, initial rewrite, evaluation, or repair. The combined conditional graph uses one Data Designer run. Without column-level failure provenance, every omitted row can only be reported as failing the coarse rewrite-combined boundary.
The required contract is a stable mapping from each terminally omitted seed row to its originating failed column, plus a safe failure category or reason. It must be available without enabling full task tracing.
Describe the solution you'd like
Expose lightweight, structured terminal row failures through the public result API for create() and preview(). If a run raises instead of returning a result, make the same provenance available on the typed exception.
The exact class and field names are flexible, but consumers need this information for each terminal failure:
@dataclass(frozen=True)
class TerminalRowFailure:
seed_record_id: str | int
column: str
failure_kind: str
reason: str | None = None
The public API should also provide a way for the caller to designate a seed identity column, for example _anonymizer_record_id, whose value is copied into seed_record_id. The returned identity must be directly joinable to the original input and must not require reconstructing it from (row_group, row_index). If no identity column is configured, Data Designer may expose a documented stable seed-row locator as a fallback.
Required semantics:
- Capture terminal row omissions after retry and salvage behavior has completed.
- Attribute the root column that failed, not downstream columns that were skipped or cancelled because their dependency was missing.
- Do not report
skip.when decisions as failures.
- Do not report transient failures that later recovered.
- Work for LLM, custom, expression, and other row-producing column types that can omit a row.
- Remain available when only part of a dataset succeeds and when every row fails.
- Be collected independently of
async_trace; do not retain prompts, completions, row contents, or successful task traces.
- Document whether failure records cover the current invocation or the full resumed run.
- Preserve deterministic input ordering where practical.
A result shape such as DatasetCreationResults.failed_records and the equivalent preview result field would satisfy the need. A lazy public artifact referenced by the result would also work if it provides the same typed, current-run contract without requiring log parsing.
Acceptance examples:
- Given two seed rows with designated IDs, if column
evaluate_0 terminally fails for one row, the result contains exactly that seed ID and column="evaluate_0".
- If downstream
repair_0 is not scheduled because evaluate_0 failed, no separate repair_0 failure is reported.
- If
repair_0 is skipped because skip.when is true, no failure is reported.
- If a retry succeeds, no terminal failure is reported.
- The same information is available without
async_trace=True and for an all-rows-failed typed exception.
Describe alternatives you've considered
- Keep the Anonymizer pipeline split across multiple Data Designer runs. This preserves coarse stage attribution but retains custom orchestration and prevents a single conditional graph from becoming the default.
- Diff input and output record IDs. This identifies omitted rows but not the column that caused the omission.
- Enable
async_trace=True and map (row_group, row_index) back to the seed. This retains every task trace, is not appropriate as a scalable production result API, and does not expose the caller's stable record ID.
- Parse warning logs, or consume proposed structured log records from #386. Logs and telemetry are useful diagnostics, but they are not a reliable post-run outcome contract and can be filtered or missed by handlers.
- Preserve failed fields as
null as proposed in #362. That changes row-retention semantics; this request only asks Data Designer to report the provenance of its existing terminal row omissions.
Agent Investigation
Investigation of current main found:
packages/data-designer/src/data_designer/interface/results.py: DatasetCreationResults exposes task_traces, but no terminal failure collection.
packages/data-designer-engine/src/data_designer/engine/dataset_builders/scheduling/task_model.py: TaskTrace contains column, row_group, row_index, status, and error, but traces are only created when tracing is enabled and do not contain a caller-provided seed identity.
packages/data-designer-engine/src/data_designer/engine/dataset_builders/async_scheduler.py: the scheduler has the originating Task when recording terminal failures and already distinguishes failures, retries, and skips internally.
packages/data-designer-engine/src/data_designer/engine/dataset_builders/dataset_builder.py: the builder exposes only the first non-retryable exception for the special zero-record error path, not per-row terminal failure provenance.
packages/data-designer/src/data_designer/interface/data_designer.py: task traces are copied to DatasetCreationResults, while terminal failure records are not returned.
Existing issues #386 and #362 are adjacent but do not provide a typed result mapping terminally omitted rows to both the originating column and the caller's seed ID.
Additional context
This is not a request for full tracing, model-call telemetry, or preservation of failed row contents. The intended surface is a lightweight correctness and failure-attribution contract for applications that embed Data Designer graphs.
Checklist
Priority Level
High (Major improvement)
Is your feature request related to a problem? Please describe.
Consumers that compose many columns into one Data Designer graph cannot determine, from the public run result, which column terminally failed for each omitted seed row.
Data Designer internally knows the task column, row group, and row index when a task fails.
DatasetCreationResults.task_tracescan expose those fields when full async tracing is enabled, but that is a heavy per-task diagnostic mechanism and the row position is not a stable caller-provided record identity. On a partially successful run, a consumer can diff input and output IDs to discover that a row disappeared, but cannot attribute that loss to the originating column without parsing logs.This blocks an integration in NVIDIA-NeMo/Anonymizer#237 and PR #240. Anonymizer's legacy rewrite implementation uses several Data Designer runs, so a missing row can be attributed to a stage such as replacement-map generation, initial rewrite, evaluation, or repair. The combined conditional graph uses one Data Designer run. Without column-level failure provenance, every omitted row can only be reported as failing the coarse
rewrite-combinedboundary.The required contract is a stable mapping from each terminally omitted seed row to its originating failed column, plus a safe failure category or reason. It must be available without enabling full task tracing.
Describe the solution you'd like
Expose lightweight, structured terminal row failures through the public result API for
create()andpreview(). If a run raises instead of returning a result, make the same provenance available on the typed exception.The exact class and field names are flexible, but consumers need this information for each terminal failure:
The public API should also provide a way for the caller to designate a seed identity column, for example
_anonymizer_record_id, whose value is copied intoseed_record_id. The returned identity must be directly joinable to the original input and must not require reconstructing it from(row_group, row_index). If no identity column is configured, Data Designer may expose a documented stable seed-row locator as a fallback.Required semantics:
skip.whendecisions as failures.async_trace; do not retain prompts, completions, row contents, or successful task traces.A result shape such as
DatasetCreationResults.failed_recordsand the equivalent preview result field would satisfy the need. A lazy public artifact referenced by the result would also work if it provides the same typed, current-run contract without requiring log parsing.Acceptance examples:
evaluate_0terminally fails for one row, the result contains exactly that seed ID andcolumn="evaluate_0".repair_0is not scheduled becauseevaluate_0failed, no separaterepair_0failure is reported.repair_0is skipped becauseskip.whenis true, no failure is reported.async_trace=Trueand for an all-rows-failed typed exception.Describe alternatives you've considered
async_trace=Trueand map(row_group, row_index)back to the seed. This retains every task trace, is not appropriate as a scalable production result API, and does not expose the caller's stable record ID.nullas proposed in #362. That changes row-retention semantics; this request only asks Data Designer to report the provenance of its existing terminal row omissions.Agent Investigation
Investigation of current
mainfound:packages/data-designer/src/data_designer/interface/results.py:DatasetCreationResultsexposestask_traces, but no terminal failure collection.packages/data-designer-engine/src/data_designer/engine/dataset_builders/scheduling/task_model.py:TaskTracecontainscolumn,row_group,row_index,status, anderror, but traces are only created when tracing is enabled and do not contain a caller-provided seed identity.packages/data-designer-engine/src/data_designer/engine/dataset_builders/async_scheduler.py: the scheduler has the originatingTaskwhen recording terminal failures and already distinguishes failures, retries, and skips internally.packages/data-designer-engine/src/data_designer/engine/dataset_builders/dataset_builder.py: the builder exposes only the first non-retryable exception for the special zero-record error path, not per-row terminal failure provenance.packages/data-designer/src/data_designer/interface/data_designer.py: task traces are copied toDatasetCreationResults, while terminal failure records are not returned.Existing issues #386 and #362 are adjacent but do not provide a typed result mapping terminally omitted rows to both the originating column and the caller's seed ID.
Additional context
This is not a request for full tracing, model-call telemetry, or preservation of failed row contents. The intended surface is a lightweight correctness and failure-attribution contract for applications that embed Data Designer graphs.
Checklist