Skip to content

Output formats

--format is accepted by validate, read, and rules list. Five formats are supported. Pick the one that matches the consumer of the output.

FormatDefault?TTY-aware colorsSchema-stableBest for
textInteractive use.
jsonCI pipelines, diffing.
csvSpreadsheet triage.
xmlLegacy integrations.
htmlSharing a report with stakeholders.

Human-readable, colored when stdout is a TTY. ANSI colors disable automatically on a non-TTY destination; force or suppress them with --force-color / --no-color.

Findings stream inline (one per line) followed by a summary block. Each finding line is:

[<severity>] <rule_id> — <message>[ — <file>:<line>][ — <field> = <value>]

Optional segments are skipped when the rule does not point at a specific file or field.

[ERROR] fk_violation — stop_id "BAD_STOP" not found in stops.txt — stop_times.txt:14203 — stop_id = BAD_STOP
[WARNING] duplicate_route_short_name — two routes share short_name "747" — routes.txt:58 — route_short_name = 747
[INFO] missing_shape — trip has no shape_id — trips.txt:1029

The summary block closes the output:

===================================
Summary
===================================
45 Errors — 94912 Warnings — 177074 Infos
Status: FAIL

With -o, findings go to the file and the console shows only per-stage progress bars and the summary.

Tabular. Columns match the canonical order of the target GTFS file (for read) or rule_id | severity | stage (for rules list).

Stable, machine-readable. Use this in CI.

{
"errors": [
{
"rule_id": "fk_violation",
"section": "foreign_key",
"severity": "Error",
"message": "stop_id \"BAD_STOP\" not found in stops.txt",
"file_name": "stop_times.txt",
"line_number": 14203,
"field_name": "stop_id",
"value": "BAD_STOP"
}
],
"summary": {
"error_count": 45,
"warning_count": 94912,
"info_count": 177074,
"passed": false
}
}

Finding schema (fields in the errors array):

FieldTypeNotes
rule_idstringRegistered rule identifier. See validation rules.
sectionstringSpec section the rule belongs to (e.g. foreign_key, csv_formatting).
severity"Error" | "Warning" | "Info"Capitalised.
messagestringHuman-readable description.
file_namestring | nullGTFS file the finding points at. null for feed-level findings.
line_numberinteger | null1-based, including the header row.
field_namestring | nullColumn implicated by the rule.
valuestring | nullActual value that triggered the rule.

Summary schema:

FieldType
error_countinteger
warning_countinteger
info_countinteger
passedboolean

passed is true iff error_count == 0 after --min-severity filtering. The exit code follows the same rule.

read emits an array of row objects keyed by column name. rules list emits an array of {rule_id, severity, stage} objects wrapped in {count, rules}.

Flat table, one row per finding (for validate) or one row per record (for read). Always includes the header line.

rule_id,section,severity,message,file_name,line_number,field_name,value
fk_violation,foreign_key,Error,"stop_id ""BAD_STOP"" not found in stops.txt",stop_times.txt,14203,stop_id,BAD_STOP

Empty cells (not null — empty string) are used when a field is not set on a given finding.

read reuses the canonical GTFS column order of the target file. rules list emits rule_id,severity,stage.

Standard XML wrapped in a <validation_report> root. The structure mirrors the JSON schema — the same field names, rendered as elements rather than keys.

<?xml version="1.0" encoding="UTF-8"?>
<validation_report>
<summary>
<error_count>45</error_count>
<warning_count>94912</warning_count>
<info_count>177074</info_count>
<passed>false</passed>
</summary>
<error>
<rule_id>fk_violation</rule_id>
<section>foreign_key</section>
<severity>Error</severity>
<message>stop_id "BAD_STOP" not found in stops.txt</message>
<file_name>stop_times.txt</file_name>
<line_number>14203</line_number>
<field_name>stop_id</field_name>
<value>BAD_STOP</value>
</error>
</validation_report>

rules list emits <rules> as the root with one <rule> element per entry.

Self-contained report. CSS and JavaScript are inlined; the file opens with a double-click in any browser — no server required. Use this when sharing a report with someone who does not live in a terminal.

Terminal window
gapline validate -f gtfs.zip --format html -o report.html

The HTML includes the summary counts, a toggleable grouping by file and by rule, and color-coded severity badges. Large reports remain navigable — the table is virtualised client-side.

Terminal window
gapline validate -f gtfs.zip --format json -o report.json
jq '.summary.error_count' report.json

text is the only format with color. Control color output with:

  • --no-color — always off, even on a TTY.
  • --force-color — always on, even when piped.
  • [output] section of gapline.tomlno_color, force_color defaults (overridden by the flags above).

See global flags.