Architecture bugs fail late and expensively. These were caught at design time.

A structural bug in a neural network does not fail in code review. It fails at forward time, on the GPU you already paid for, sometimes hours into a run. Neurarch keeps your model as a typed graph and runs the structural checks while you design, so the crash below never leaves the editor. This page shows the recurring bug classes and the measured evidence that the checks track reality.

This is the floor, not the product. Everything on this page is a design that would have crashed, and a crash is the cheap half: one forward pass with a dummy batch finds it too. The expensive half never errors at all. Two CIFAR-10 designs that both clear every check on this page, ours included, trained to 71.7% and 20.1%, and no static score separated them. Telling those two apart before you pay to train both is the problem Neurarch is actually built for; the checks below are what make that measurable.

The measurement first

We generated clean reference architectures plus systematically corrupted variants (broken attention divisibility, linear width mismatches, severed connections), built every graph as a real PyTorch model, and cross-tabulated the verifier verdict against what actually happened. 264 graphs, two seeds, torch 2.8. Every row is published, one per graph, with the verifier verdict beside what PyTorch actually did: the grounding study dataset.

Two commands reproduce the table below, from neurarch-ai/neurarch-arch-bench. No API key, no GPU, no account:

node training/dump_grounding_set.mjs --count=80 --seed=123 --out=g.jsonl
python training/grounding.py --set g.jsonl --steps 60

That builds every graph as a real PyTorch model on CPU and writes the verdict beside what torch did, which is the file the numbers here are counted from (grounding_results.csv, torch 2.8, seed 123). If your run disagrees with this table, the table is what is wrong.

Verifier verdictnPyTorch forwardMakes training progress
PASS (clean)80100% ok90%
BLOCKED960% ok (96/96 crash)0%
Corrupted, missed by a simple rubric880% ok0%
96/96
Designs the verifier blocked that crashed PyTorch forward
80/80
Designs it cleared that built and ran
88
More corrupted graphs a simple rubric waves through and PyTorch still rejects. The in-product shape engine flags every one

Read it honestly: at this scale a blocker predicts runtime failure perfectly, and clean graphs overwhelmingly construct and train. The third number is the point of this page. Those 88 are linear width mismatches that pass the open benchmark's deliberately simple rubric but still crash PyTorch, and the in-product shape engine does flag them (case 2 below). That gap is the difference between shipping a checker and shipping a rubric. "Makes training progress" means loss fell at least 20% in 60 steps; it is a trainability probe, not a quality claim.

The gallery

Each case is a check that runs live in the editor. The red side is what PyTorch says when the same bug ships to the GPU.

1. Attention head count does not divide the embedding dim

embed_dim 768 with 10 heads. Looks fine in code review; 768 / 10 is not an integer.

Caught in the editor
shape check: embedDim % numHeads != 0 (768 % 10). Blocking. One-click fix snaps heads to the nearest divisor.
If it ships
AssertionError: embed_dim must be divisible by num_heads

Crashes when the module is constructed on the training node, after the job was queued, the container pulled, and the dataset downloaded.

Load this exact bug in the editor and watch the check fire. No account needed.

2. Linear layer width does not match its upstream output

Upstream block outputs 512 features; the next Linear declares in_features=768. The bug class that simple linters miss (row 3 in the table above).

Caught in the editor
shape propagation: this layer's inFeatures (768) does not match the upstream output (512). One-click fix sets it from the propagated shape.
If it ships
RuntimeError: mat1 and mat2 shapes cannot be multiplied (32x512 and 768x256)

Fails on the first batch. In our measurement, 100% of graphs with this corruption failed forward.

Load this exact bug in the editor and watch the check fire. No account needed.

3. Two branches merge with different shapes

A residual add where one branch was projected to 256 and the other stayed at 512.

Caught in the editor
merge check: both inputs to this add must have the same shape. Deterministic fix inserts the missing projection (or a reshape when only the layout differs).
If it ships
RuntimeError: The size of tensor a (512) must match the size of tensor b (256) at non-singleton dimension 1

The classic skip-connection bug. It survives until the exact batch that hits the mismatched path.

Load this exact bug in the editor and watch the check fire. No account needed.

4. Grouped-query attention with a head ratio that does not divide

numHeads=12, numKVHeads=5. GQA implementations require the query heads to group evenly over the KV heads.

Caught in the editor
GQA check: numHeads % numKVHeads != 0 (12 % 5). Blocking, with a one-click snap to the nearest valid KV head count.
If it ships
assert num_heads % num_kv_heads == 0 (raises at module init or silently mis-groups, depending on the implementation)

The silent variant is the expensive one: some hand-rolled GQA code repeats KV heads incorrectly instead of failing.

Load this exact bug in the editor and watch the check fire. No account needed.

5. A connection that quietly severs or cycles the graph

A refactor deletes one edge and part of the network no longer feeds the output, or a new edge closes a cycle.

Caught in the editor
graph checks: orphan detection (a layer lands disconnected) and DFS cycle detection on every proposed edge, including edits proposed by the AI agent.
If it ships
forward() fails, or worse: it runs, and the dead branch's parameters train to nothing while metrics look plausible.

In our corrupted set, severed graphs failed forward 100% of the time. The ones that do run are a slower, subtler waste.

What a shipped bug costs

Example arithmetic, not a promise: a 10-epoch fine-tune on one A100 80GB at $4.20/hr that dies 6 hours in wastes about $25 plus the engineer-day spent bisecting it. A multi-node pretraining run that crashes at step one wastes the whole cluster spin-up; one that trains a dead branch wastes the full budget. Inside the app, every blocking finding shows the estimated cost of the run it puts at risk, using your own GPU, epoch, and dataset settings.

Run the checks on your own architecture, free
Measurement methodology and raw scripts: neurarch-arch-bench (grounding study under training/). Error messages are verbatim PyTorch 2.x. Neurarch: neurarch.com.