Skip to content

EasyEDA rate-limits with HTTP 403; surfaced as "Failed to search for the component" #409

Description

@itsbalamurali

Summary

EasyEDA's component API rate-limits by IP and answers with HTTP 403 once
tripped — not 429, and with no Retry-After. fetchEasyEDAComponent treats any
non-success response as a lookup failure, so the whole batch surfaces as:

Async effect error in PcbFootprintStringRender "load-lib-footprint":
Error: Failed to search for the component
    at fetchEasyEDAComponent (...)
    at async JlcPcbPartsEngine.fetchPartCircuitJson (...)
    at async jlcpcb (...)

The message points at the component, which sends you looking for a bad part
number. The part is fine; the request was throttled.

Reproduction

A board with ~10 footprint="jlcpcb:C…" strings resolves them concurrently on
render and reliably trips the limit. It reproduces directly against the API:

U="https://easyeda.com/api/products/C11702/components?version=6.4.19.5"
for i in $(seq 1 20); do curl -s -o /dev/null -w "%{http_code} " "$U"; done

Output goes 200 200 … 403 403 403. Recovery measured on a single IP:

immediately: 403
  + 20s -> 403
  + 40s -> 403
  + 60s -> 403
  + 80s -> 403
  +100s -> 403
  +120s -> 200

So roughly a two-minute cooldown.

Things it is not

Worth stating, because both look plausible and both are wrong:

  • Not the part. Every LCSC id I tried behaved identically, and all resolve
    fine once the cooldown expires.
  • Not the User-Agent. Mid-cooldown every UA 403s — browser strings,
    curl/8.4.0, a custom string, and no UA header at all. Before the limit is
    tripped, all of them return 200. I initially misread partial data as
    UA-based blocking; a wider sweep ruled it out.

Impact

  • A warm local cache hides it, so it fails for new contributors and in CI while
    working on the maintainer's machine.
  • Failures cascade: one throttled batch fails every footprint in it.
  • The error text sends users hunting for a nonexistent part-number problem.

Suggestions

  1. Throttle/serialise parts-engine fetches instead of firing the batch at once.
  2. Retry 403 with backoff — the cooldown is short and bounded.
  3. Distinguish "rate limited" from "not found" in the error text. Right now they
    are indistinguishable, and only the second one is the user's problem.
  4. Consider proxying through tscircuit infrastructure, as
    modelcdn.tscircuit.com already does for 3D models, so one shared cache
    absorbs the limit rather than every user's IP hitting it directly.

Related

easyeda-converter has a long run of [Cxxxxxxx] Failed to import from JLCPCB
issues (#223, #240, #262, #268, #272, #275, #288, #314, …), each filed against a
specific part. It may be worth checking how many are actually this, since a
throttled lookup is indistinguishable from a genuinely missing part in the
current message.

Versions

  • tscircuit CLI 0.0.2132, @tscircuit/core 0.0.1484, @tscircuit/props 0.0.587
  • also reproduced in the browser runtime, bun 1.3.14, macOS arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions