The quiet failure is the one with no diagnostics, and it exits 0
Measured on 0.8.9, two paths for the same command:
| outcome |
exit |
trace rows |
found but blocked — error[CAPABILITY_DENIED] |
3 |
6 (consulted: … / not consulted (an earlier source answered)) |
found nothing — metadata-only: no OA PDF available |
0 |
0 |
$ doiget fetch 10.1137/0117004 ; echo "EXIT=$?"
fetched doi:10.1137/0117004 (metadata-only: no OA PDF available) -> …/doi_10.1137_0117004.toml
"On the Continuity of the Generalized Inverse" by Stewart, G. W. (1969) [crossref/closed]
EXIT=0
That line is byte-identical whether the six optional sources were on and had nothing or off and
never asked. I checked both: the found-nothing path prints no trace in either case.
Which is exactly the distinction #413 built the trace for —
"We asked and it had nothing" and "we never asked" are different problems with different fixes, and
were previously the same observable.
— absent on the path where it is most misleading, because that path is not an error and so has no
error[…] block to hang the trace on. #445 extended the trace from NOT_FOUND to the blocked
content leg; this is the third case, and the only one that reads as a result.
Why it matters more than the exit code suggests. A user searching for a paper reads
no OA PDF available as "this paper has no OA copy". With the default profile that sentence means
only "Crossref, Unpaywall and arXiv have nothing" — three of eleven sources. I concluded twice today
that a paper was unreachable on the strength of it, and had to redo the search. A narrow default is
the right design (#413: "the default binary is narrow, rate-capped, provenance-logged and
ToS-clean"); a narrow default that does not say it is narrow is a different thing.
What the failure should return
Three parts, in this order.
1. What was actually consulted this run
The rows already exist on the other two paths. Emit them here too, and make the disabled ones
visible rather than absent — an omitted row and a row saying "off" are not the same message:
no OA copy found for 10.1137/0117004.
consulted:
crossref answered (metadata; oa_status = closed)
unpaywall answered: no OA location
arxiv answered: no preprint
not consulted (disabled):
datacite doaj europe-pmc hal openaire core openalex
2. The command that widens it
Not prose — the line to paste. #478 is the precedent to follow, and its complaint applies here too:
the machine path already computes which flag actually covers the case while the human path prints a
generic suggestion. Here the exact set is known, so:
to widen the search:
DOIGET_ENABLE_OPENALEX=1 DOIGET_ENABLE_CORE=1 DOIGET_ENABLE_OPENAIRE=1 \
DOIGET_ENABLE_HAL=1 DOIGET_ENABLE_EUROPE_PMC=1 DOIGET_ENABLE_DATACITE=1 \
doiget fetch 10.1137/0117004
with the two that carry an extra prerequisite named as such — CORE (DOIGET_CORE_API_KEY, free)
and OPENALEX (needs --features citation) — so a user does not enable one and silently get a
degraded answer.
#470 is the blocker for doing this per-row: classify_attempt throws the DenialContext away, so an
attempt row cannot carry its own remediation today.
3. Which one is most likely — ranked, never filtered
This is the part that does not exist yet, and the one worth being careful about: a ranking that is
wrong is worse than no ranking, because it makes people stop early. So it must be an ordering of
the full list, never a shortlist, and it must name the signal it ranked on.
The strong case: OpenAlex turns the guess into a lookup. It reports locations directly, and on
the three DOIs I tested today it separates the two situations cleanly:
| DOI |
OpenAlex locations |
truth |
10.1098/rspa.2014.0585 |
5 — incl. Europe PMC PMC4277194 and two Oxford ORA records |
free PDF really is at Europe PMC (670 kB, fetched) |
10.1007/bf02551288 |
1 — publisher landing page only |
nothing anywhere |
10.1137/0117004 |
1 — publisher landing page only |
nothing anywhere |
3/3, and n=3 — not a validated heuristic, but the mechanism is not statistical: OpenAlex is listing
the hosts, so with it enabled the answer is "Europe PMC has it", not "Europe PMC might". That makes
DOIGET_ENABLE_OPENALEX the first thing to suggest, and it is cheap: one metadata call, no
retrieval. (Consuming those locations to actually fetch is #461; this issue only asks to report
them.)
The fallback, when OpenAlex is off: rank from metadata already in hand after the Crossref leg —
no extra network. Signals, strongest first:
- DOI prefix → registrant. doiget already maintains a prefix→publisher map for Tier-3 scoping
(ADR-0041); the same map says whether an enabled-able TDM source covers this prefix at all.
- venue / subject → Europe PMC for anything PMC indexes (and note it indexes well beyond
biomedical — the Royal Society paper above is in it).
- author affiliation / funder → HAL for a French institution, OpenAIRE for an EU funder.
- CORE last, always present. Its own module doc calls it "the broadest single OA index outside
Unpaywall and therefore the LAST fallback in the chain" — so it is never the top suggestion and
never absent from the list.
Rendered:
most likely to hold it, given "SIAM J. Appl. Math., 1969, prefix 10.1137":
1. openalex lists every known location — turns this ranking into a lookup
2. core broadest cross-repository index (needs DOIGET_CORE_API_KEY, free)
3. openaire European repository aggregation
…and 4 more, above.
ranked on: venue, DOI prefix, year. This is a guess, not a report — 1. is not.
That last line matters. Items 2+ are heuristics over metadata; item 1 is a claim about what an index
says. Presenting them in one list without marking which is which would be the failure mode this
whole issue is about.
Scope
Reporting only — no new retrieval, no new source, no change to what gets tried. Adjacent and
distinct: #461 (actually try the repository copies), #470 (the remediation plumbing this needs),
#478 (compute the precise suggestion instead of a generic one), #497 (write down the ceiling that
now holds).
The quiet failure is the one with no diagnostics, and it exits 0
Measured on 0.8.9, two paths for the same command:
error[CAPABILITY_DENIED]consulted: …/not consulted (an earlier source answered))metadata-only: no OA PDF availableThat line is byte-identical whether the six optional sources were on and had nothing or off and
never asked. I checked both: the found-nothing path prints no trace in either case.
Which is exactly the distinction #413 built the trace for —
— absent on the path where it is most misleading, because that path is not an error and so has no
error[…]block to hang the trace on. #445 extended the trace fromNOT_FOUNDto the blockedcontent leg; this is the third case, and the only one that reads as a result.
Why it matters more than the exit code suggests. A user searching for a paper reads
no OA PDF availableas "this paper has no OA copy". With the default profile that sentence meansonly "Crossref, Unpaywall and arXiv have nothing" — three of eleven sources. I concluded twice today
that a paper was unreachable on the strength of it, and had to redo the search. A narrow default is
the right design (#413: "the default binary is narrow, rate-capped, provenance-logged and
ToS-clean"); a narrow default that does not say it is narrow is a different thing.
What the failure should return
Three parts, in this order.
1. What was actually consulted this run
The rows already exist on the other two paths. Emit them here too, and make the disabled ones
visible rather than absent — an omitted row and a row saying "off" are not the same message:
2. The command that widens it
Not prose — the line to paste. #478 is the precedent to follow, and its complaint applies here too:
the machine path already computes which flag actually covers the case while the human path prints a
generic suggestion. Here the exact set is known, so:
with the two that carry an extra prerequisite named as such —
CORE(DOIGET_CORE_API_KEY, free)and
OPENALEX(needs--features citation) — so a user does not enable one and silently get adegraded answer.
#470 is the blocker for doing this per-row:
classify_attemptthrows theDenialContextaway, so anattempt row cannot carry its own remediation today.
3. Which one is most likely — ranked, never filtered
This is the part that does not exist yet, and the one worth being careful about: a ranking that is
wrong is worse than no ranking, because it makes people stop early. So it must be an ordering of
the full list, never a shortlist, and it must name the signal it ranked on.
The strong case: OpenAlex turns the guess into a lookup. It reports
locationsdirectly, and onthe three DOIs I tested today it separates the two situations cleanly:
locations10.1098/rspa.2014.0585PMC4277194and two Oxford ORA records10.1007/bf0255128810.1137/01170043/3, and n=3 — not a validated heuristic, but the mechanism is not statistical: OpenAlex is listing
the hosts, so with it enabled the answer is "Europe PMC has it", not "Europe PMC might". That makes
DOIGET_ENABLE_OPENALEXthe first thing to suggest, and it is cheap: one metadata call, noretrieval. (Consuming those locations to actually fetch is #461; this issue only asks to report
them.)
The fallback, when OpenAlex is off: rank from metadata already in hand after the Crossref leg —
no extra network. Signals, strongest first:
(ADR-0041); the same map says whether an enabled-able TDM source covers this prefix at all.
biomedical — the Royal Society paper above is in it).
Unpaywall and therefore the LAST fallback in the chain" — so it is never the top suggestion and
never absent from the list.
Rendered:
That last line matters. Items 2+ are heuristics over metadata; item 1 is a claim about what an index
says. Presenting them in one list without marking which is which would be the failure mode this
whole issue is about.
Scope
Reporting only — no new retrieval, no new source, no change to what gets tried. Adjacent and
distinct: #461 (actually try the repository copies), #470 (the remediation plumbing this needs),
#478 (compute the precise suggestion instead of a generic one), #497 (write down the ceiling that
now holds).