Skip to content

FAQ

Why is gapline faster than gtfs-validator?

Section titled “Why is gapline faster than gtfs-validator?”

Three things:

  1. No JVM cold start. gapline is a static Rust binary. gtfs-validator pays a second or two of JVM startup on every run, which dominates small-feed workloads.
  2. In-memory parallelism. Validation runs rules in parallel across rows using rayon. Rules that can work independently on different files or different row ranges do so without locking.
  3. Contiguous data layout. The core feed representation is Vec-based with reverse indexes built once at load time. No object graph, no per-row heap allocation during validation.

On a mid-sized real-world feed, this adds up to 7–9× faster end-to-end validation. On a small feed (under 1 MB), the JVM startup penalty pushes the ratio closer to 90×.

No. gapline targets GTFS Schedule only — the static timetable feed. GTFS-Realtime is a separate protobuf-based spec (trip updates, vehicle positions, service alerts) and is out of scope for this tool.

Not without forking today. Rules are compiled into the binary; there is no plugin interface or scripting hook. If you have a rule that belongs in the default suite, open an issue on GitHub — most of the current rules landed that way.

For ad-hoc checks, a gapline read <target> --where "..." --format json call piped through jq covers most one-off validations.

My feed fails structural validation. What does that mean?

Section titled “My feed fails structural validation. What does that mean?”

Structural validation is the first stage. It checks that the archive has the required files, that they parse as CSV, and that the required columns are present. Downstream validation stages (fields, references, semantics) do not run meaningfully when structural issues are present — fixing them is always step one.

Common structural errors: a missing required file (stops.txt, routes.txt, trips.txt, stop_times.txt), a file that is not valid UTF-8, a row with fewer columns than the header declares.

Yes. Run in PowerShell:

Terminal window
Invoke-WebRequest https://gapline.dev/install.ps1 | Invoke-Expression

The installer drops gapline.exe into %USERPROFILE%\.local\bin and updates the user PATH. See installation for details.

No. gapline is 100% offline. It never contacts a network service, never reads or writes anything outside the files you pass on the command line and the config chain (./gapline.toml, ~/.config/gapline/config.toml).

If a corporate firewall or sandbox blocks outbound traffic, gapline works the same way as on a fully connected machine.

Does gapline work on feeds that are not UTF-8?

Section titled “Does gapline work on feeds that are not UTF-8?”

No. GTFS is specified as UTF-8; gapline rejects non-UTF-8 files with a clear message (which file, which byte offset). If an agency ships Latin-1 or Windows-1252 data, transcode it with iconv before handing it to gapline. See fixing common issues.

Real-world tests run on feeds with several million stop_times rows without issue. The main bottleneck is available RAM — the feed is held in memory — but the representation is compact (single-digit megabytes for a typical agency feed).

If you hit a memory ceiling on a very large feed, split the archive by agency or by date range before validating.

.gl files chain several gapline commands into a single reproducible script. The feed is loaded once, each command acts on the in-memory copy, and a single atomic write at the end persists the result. It is the right tool for weekly cleanups, CI-driven patching, or anything you want to version-control.

See writing .gl scripts for a walkthrough and .gl syntax for the grammar.

Because a delete on a relational feed has a larger blast radius than the command line suggests — removing a stop may cascade to hundreds of stop_times rows. The prompt shows the full cascade preview before anything is applied. Pass --confirm to skip it in scripts, but preview the match set with gapline read first.

Yes. The Linux install script works inside any glibc-based image. Example minimal stage:

FROM debian:stable-slim
RUN apt-get update && apt-get install -y curl ca-certificates \
&& curl -fsSL https://gapline.dev/install.sh | sh -s -- --version 1.0.1 \
&& ln -s /root/.local/bin/gapline /usr/local/bin/gapline
ENTRYPOINT ["gapline"]

For Alpine / musl, build from source — the static binary from the install script is glibc-based today.

How do I find the ID of a rule to disable?

Section titled “How do I find the ID of a rule to disable?”
Terminal window
gapline rules list
gapline rules list --severity warning
gapline rules list | grep -i speed

Feed the matching ID to --disable-rule:

Terminal window
gapline validate -f gtfs.zip --disable-rule speed_validation

Shell completion also suggests registered IDs — see shell completion.

  • Introduction — what gapline is and why it exists.
  • Quickstart — first validation in five minutes.
  • Concepts — the foundational ideas behind the CLI.