Semaphor
Data Apps

Validation And Debugging

Understand SDK validation, execution diagnostics, and common Data App errors.

Data Apps have two layers of feedback:

  • SDK validation catches malformed specs before or during query construction.
  • Execution diagnostics explain what happened during governed server-side execution.

Use both. Validation keeps generated code honest. Diagnostics tell you how Semaphor resolved data, relationships, filters, and result status.

Start With Query Status

Every query hook returns a status:

const result = useSemaphorQuery(revenueByCampaign);

if (result.status === 'loading' && !result.isStale) return <Loading />;
if (result.status === 'error') return <Error error={result.error} />;
if (result.isPartial) return <PartialResultWarning result={result} />;
if (result.status === 'success') {
  return (
    <>
      {result.isStale ? <RefreshingBadge /> : null}
      <Chart rows={result.records} />
    </>
  );
}

Do not render zeros for loading data. A zero should mean the query succeeded and returned zero. During a refetch, isStale can be true while the hook keeps the previous successful payload available for rendering.

Inspect Execution Result

Governed queries may return executionResult.

const execution = result.executionResult;

console.log(execution?.status);
console.log(execution?.rowCount);
console.log(execution?.relationshipDiagnostics);

Use this when a query is partial, missing a relationship, or returning unexpected rows.

For analysis results, executionResult is authoritative. Top-level fields are display conveniences. Full field lineage, including validated derived-field definitions, belongs under executionResult.fieldsUsed; compact top-level fieldsUsed does not carry derivedField.

Common Validation Problems

ProblemWhat it usually meansFix
Unknown sourceThe source ref does not match a visible semantic dataset.Use the domainId and datasetName returned by Semaphor discovery; include datasetId when available.
Missing fieldA field name does not exist on the source.Check the dataset schema.
Wrong field roleA measure was authored as a dimension, or a dimension as a measure.Use semaphor.field.measure, dimension, date, or id correctly.
Missing measureKPI/analysis query has no measure.Add measures and primaryMeasure.
Unsupported joined projectionA related field is not projection-safe.Use a dimension/date/id field or model the relationship safely.
Invalid option populationrelated_population is missing a valid base source.Add population: { kind: 'related_population', baseSource }.

Relationship Diagnostics

Relationship-aware queries can return relationship diagnostics.

const diagnostics = result.executionResult?.relationshipDiagnostics;

relationshipDiagnostics.status uses the shared analytics protocol enum:

not_required
resolved
missing
ambiguous
fanout_risk
unknown

Specific causes, such as missing option population, incomplete composite keys, or temporal relationship requirements, are surfaced through diagnostic messages, warnings, and repair hints. Example: if fact_orders can reach dim_customer through buyer, bill-to, and ship-to relationships, "revenue by customer segment" should return status: 'ambiguous' instead of guessing.

"Failed To Fetch"

Failed to fetch usually means the browser could not complete the request. Check:

  • Is SemaphorDataAppProvider mounted?
  • Does the provider have a token?
  • Does the token include the expected API base URL?
  • Is the API server reachable?
  • Is CORS configured for the local app?
  • Did too many queries fire at once during local development?

When the request reaches Semaphor and fails inside governed execution, prefer the structured error and executionResult fields over the browser fetch message.

Row Rendering Gotchas

Do not use column labels as object keys. Use columns[].key.

{result.columns?.map((column) => (
  <td key={column.key}>{String(row[column.key] ?? '')}</td>
))}

Joined results can contain duplicate field names such as name, id, or status from different datasets. Semaphor returns stable column keys to preserve both values.

Relationship Debug Checklist

If a joined filter or joined projection fails:

  1. Confirm the base query source.
  2. Confirm every field has the right source.
  3. Confirm the related source is in the same semantic domain.
  4. Confirm the semantic model has an active relationship path.
  5. Check if there are multiple valid paths and add a relationship id hint only if needed.
  6. Check fanout diagnostics before showing joined measures.
  7. Use SQL fallback only when semantic builders cannot express the request.

On this page