es-client: non-JSON error responses report "Body is unusable" instead of the HTTP status
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 75/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- nodejs, typescript
- Ambito
- backend-api-design, cli
Direzione di ricerca
Il bug si trova in src/lib/es-client.ts righe 125-132. Inizia leggendo il file per comprendere il flusso delle richieste. La correzione consiste nel leggere prima il corpo della risposta come testo, quindi provare a analizzarlo come JSON, in modo simile a come lo gestiscono kibana-client.ts e cloud-client.ts. Scrivi un test per riprodurre l'errore utilizzando un server HTTP simulato che restituisce una risposta di errore non JSON, quindi verifica che la correzione restituisca il codice di stato e il corpo corretti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
Any non-2xx response whose body is not valid JSON surfaces as Error: Body is unusable: Body has already been read, losing the status code. That is undici's TypeError — the error branch of
EsClient.request reads the body twice. Deterministic, not timing-dependent.
The usual way to hit it is a reverse proxy in front of Elasticsearch: proxy_read_timeout expiring
on a long ES|QL query returns an nginx HTML 504, and the CLI reports Body is unusable instead of
504 — pointing suspicion at the client rather than the proxy.
Root cause
src/lib/es-client.ts#L125-L132:
if (!response.ok) {
let body: unknown
try {
body = await response.json() // consumes the stream
} catch {
body = await response.text() // ← throws: body already consumed
}
throw new EsResponseError(response.status, body)
}
response.json() disturbs the body even when it rejects, so the catch branch can never read it.
Reproduction
cat > elasticrc-local.yml <<'YAML'
current_context: local
contexts:
local:
elasticsearch:
url: http://127.0.0.1:9999
auth: { api_key: ZmFrZTpmYWtl }
YAML
chmod 0600 elasticrc-local.yml
export ELASTIC_CLI_CONFIG_FILE="$PWD/elasticrc-local.yml" NO_PROXY=localhost,127.0.0.1
# stand in for "ES behind a proxy that timed out"
node -e 'require("http").createServer((q,s)=>{s.writeHead(504,{"content-type":"text/html"});s.end("<html><body>504 Gateway Time-out</body></html>")}).listen(9999,"127.0.0.1")' &
elastic es esql query --query 'FROM x | LIMIT 1' --format txt
# Error: Body is unusable: Body has already been read (exit 1)
Same for 502, 503, text/plain and empty bodies. A JSON error body works correctly
(Error: illegal_argument_exception: …). Reproduced on v0.4.0 and v0.5.0, Node v26.8.1,
Linux x86_64, against Elasticsearch 9.5.3.
Suggested fix
Read once, then parse — as kibana-client.ts#L212
and cloud-client.ts#L75
already do in this repo:
const text = await response.text()
let body: unknown
try {
body = JSON.parse(text)
} catch {
body = text
}
throw new EsResponseError(response.status, body)
EsResponseError's message should also carry the status, since a string body currently renders as
bare HTML. Happy to open a PR with tests for an HTML and an empty error body.
Context
Introduced by #281 (native-fetch EsClient); @elastic/transport handled it correctly. Present in
every release since v0.2.0 and on main today. #588 fixed the same blind-JSON.parse mistake on
the success branch of this file — this is the error branch.
- Lingua principale
- TypeScript
- Stelle
- 43
- Fork
- 24
- Merge medio
- 1g 5h
- PR unite (30g)
- 61
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di elastic/cli
-
cloud enhancement
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
mksglu/context-mode#1200 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
jaegertracing/jaeger-ui#4506 ·
-
area:desktop area:ui bug platform:macos
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
anthropics/claude-code#96687 ·
-
good first issue
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 95/100
AOSSIE-Org/DebateAI#582 · 2 commenti ·