Skip to content

fix: require pinHeader pinCount to be a positive integer (#756)#757

Closed
DPS0340 wants to merge 1 commit into
tscircuit:mainfrom
DPS0340:fix/pinheader-pincount-integer
Closed

fix: require pinHeader pinCount to be a positive integer (#756)#757
DPS0340 wants to merge 1 commit into
tscircuit:mainfrom
DPS0340:fix/pinheader-pincount-integer

Conversation

@DPS0340

@DPS0340 DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown

Fixes #756. Independent of my #755 (different file) — either order.

What was wrong

pinCount: z.number() accepted fractional, zero, negative and infinite values. The fractional case is the damaging one — it produces a header whose ports and pads disagree, silently:

pinCount source_ports pads errors
2 2 2 0
2.5 2 3 0
3 3 3 0
3.7 3 4 0
4 4 4 0

Every whole number agrees; every fractional one leaves a pad with no port behind it. That renders and exports without complaint.

Zero and negative counts fail too, but later and misleadingly — they surface as pcb_missing_footprint_error, which points at the footprint when the mistake was the count.

The fix

- pinCount: z.number(),
+ pinCount: z.number().int().positive(),

.int() catches the fractional case, .positive() catches 0 and negatives, and together they also reject Infinity (which z.number() lets through — it only excludes NaN).

This is the idiom the repo already uses: lib/components/analogacsweepsimulation.ts has z.number().int().positive() for sampleCount and samplesPerInterval. No new convention.

Scope

pinCount only. I checked the neighbouring schemas rather than assuming — it's the sole bare z.number() in pin-header.ts, and breakout.ts / chip.ts have no comparable count field taking a raw number. Anything broader would be speculative.

Tests

tests/pin-header-pin-count.test.ts, six tests pinning both directions:

case expected
1, 4, 40 accepted
2.5, 3.7 rejected
0, -4 rejected
NaN, Infinity rejected
no pinCount at all still rejected — the guard must not make a required prop optional
pinCount: 8 parses through to 8 unchanged

The last two rows are the guard rails: a change that made the field optional, or that coerced values, would break them while a bare "rejects bad input" check would not.

Bite-proofed: reverting only lib/components/pin-header.ts takes the file from 6 pass to 3 pass / 3 fail.

Verification

bun test: 389 pass / 0 fail (baseline on main is 383 pass / 0 fail; +6 new). bunx tsc --noEmit clean, bun run format:check clean.

@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Author

Withdrawing this one on queue grounds rather than anything about the change itself.

I counted my own output across every repo I contribute to. Among PRs a maintainer actually decided, 57% merged — but 94% of what I have opened has never been looked at by a human at all. The constraint was never quality; I was handing out more review work than anyone could absorb.

This PR fixes an issue I filed myself, which is the shape most of that volume took: find something, report it, fix it, and hand a maintainer work nobody asked for. I am closing the self-originated ones across every repo and keeping only those that answer someone else's bug report.

The branch stays up and the issue stays open, so nothing is lost. If this one is actually wanted, say so and I will reopen it.

Sorry for the noise.

@DPS0340 DPS0340 closed this Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pinHeader pinCount accepts fractional, zero, negative and infinite values

1 participant