fix(extensions/huggingface): bound model discovery JSON response read to prevent OOM#101079
Conversation
0f93d27 to
fd7bed5
Compare
|
Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 6:24 PM ET / 22:24 UTC. Summary PR surface: Source +4, Tests +62. Total +66 across 2 files. Reproducibility: yes. source-level: current main and latest release still call native Review metrics: 2 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land exactly one Hugging Face bounded-reader PR that reuses the plugin SDK helper, preserves static-catalog fallback, and has direct changed-path proof or an explicit maintainer proof override. Do we have a high-confidence way to reproduce the issue? Yes, source-level: current main and latest release still call native Is this the best way to solve the issue? Yes for the code shape: reusing the plugin SDK bounded JSON reader is the narrow owner-boundary fix. The best landing path remains unsettled until maintainers choose between this branch and the proof-sufficient overlapping PR and resolve proof expectations. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 17d3c2eb0a80. Label changesLabel justifications:
Evidence reviewedPR surface: Source +4, Tests +62. Total +66 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
9b3d800 to
58a611a
Compare
Maintainer land-ready proofReviewed exact head: The model-discovery success body is now consumed at the Hugging Face plugin's HTTP boundary through the shared 16 MiB provider JSON reader. Overflow cancels the response stream and enters the existing static-catalog fallback; a valid small streamed response still discovers dynamic models. Evidence:
Local review commands:
Sanitized direct AWS Crabbox was attempted twice, but the broker rejected lease creation with HTTP 500 code 1101. No contributor code ran on a credential-hydrated Testbox; the exact-SHA release gate is the execution proof backend. Best-fix judgment: this is the narrow owner-boundary fix. A downstream model-list guard would buffer too late, and a plugin-local response helper or cap would duplicate the shared provider HTTP contract. Direct duplicates #97743 and #96480 can close after this lands; #98941 retains distinct Discord and thread-ownership changes. No screenshot applies: this is a provider response-stream boundary change. |
|
Merged via squash.
|
… to prevent OOM (openclaw#101079) * fix(extensions/huggingface): bound model discovery JSON response read to prevent OOM * test(huggingface): prove bounded discovery cleanup * test(huggingface): avoid unbound reader assertions --------- Co-authored-by: Peter Steinberger <[email protected]>
…mantics The thread-ownership 409 conflict path still used unbounded resp.json(), inconsistent with the bounded readers shipped across the other channel/provider success paths. A compromised or buggy forwarder returning a multi-GB 409 body would buffer the entire body before JSON.parse, OOMing the agent. Bound the 409 body via readResponseTextLimited (8 KiB cap; a 409 owner field is ~30 bytes). Wrap the parse in try/catch so a truncated or malformed 409 body still cancels the send (owner logged as "unknown") — the 409 status itself means another agent owns this thread, independent of body parseability. The discord webhook and huggingface /v1/models success reads from the original PR were superseded upstream by openclaw#98098 and openclaw#101079 (readProviderJsonResponse), so this branch now carries only the thread-ownership fix. Co-Authored-By: Claude <[email protected]>
… to prevent OOM (openclaw#101079) * fix(extensions/huggingface): bound model discovery JSON response read to prevent OOM * test(huggingface): prove bounded discovery cleanup * test(huggingface): avoid unbound reader assertions --------- Co-authored-by: Peter Steinberger <[email protected]>
…mantics The thread-ownership 409 conflict path still used unbounded resp.json(), inconsistent with the bounded readers shipped across the other channel/provider success paths. A compromised or buggy forwarder returning a multi-GB 409 body would buffer the entire body before JSON.parse, OOMing the agent. Bound the 409 body via readResponseTextLimited (8 KiB cap; a 409 owner field is ~30 bytes). Wrap the parse in try/catch so a truncated or malformed 409 body still cancels the send (owner logged as "unknown") — the 409 status itself means another agent owns this thread, independent of body parseability. The discord webhook and huggingface /v1/models success reads from the original PR were superseded upstream by openclaw#98098 and openclaw#101079 (readProviderJsonResponse), so this branch now carries only the thread-ownership fix. Co-Authored-By: Claude <[email protected]>
… to prevent OOM (openclaw#101079) * fix(extensions/huggingface): bound model discovery JSON response read to prevent OOM * test(huggingface): prove bounded discovery cleanup * test(huggingface): avoid unbound reader assertions --------- Co-authored-by: Peter Steinberger <[email protected]> (cherry picked from commit a464620)
…mantics (#98941) * fix(thread-ownership): bound 409 response read and preserve cancel semantics The thread-ownership 409 conflict path still used unbounded resp.json(), inconsistent with the bounded readers shipped across the other channel/provider success paths. A compromised or buggy forwarder returning a multi-GB 409 body would buffer the entire body before JSON.parse, OOMing the agent. Bound the 409 body via readResponseTextLimited (8 KiB cap; a 409 owner field is ~30 bytes). Wrap the parse in try/catch so a truncated or malformed 409 body still cancels the send (owner logged as "unknown") — the 409 status itself means another agent owns this thread, independent of body parseability. The discord webhook and huggingface /v1/models success reads from the original PR were superseded upstream by #98098 and #101079 (readProviderJsonResponse), so this branch now carries only the thread-ownership fix. Co-Authored-By: Claude <[email protected]> * fix(thread-ownership): bound forwarder conflict handling --------- Co-authored-by: Claude <[email protected]>
…mantics (openclaw#98941) * fix(thread-ownership): bound 409 response read and preserve cancel semantics The thread-ownership 409 conflict path still used unbounded resp.json(), inconsistent with the bounded readers shipped across the other channel/provider success paths. A compromised or buggy forwarder returning a multi-GB 409 body would buffer the entire body before JSON.parse, OOMing the agent. Bound the 409 body via readResponseTextLimited (8 KiB cap; a 409 owner field is ~30 bytes). Wrap the parse in try/catch so a truncated or malformed 409 body still cancels the send (owner logged as "unknown") — the 409 status itself means another agent owns this thread, independent of body parseability. The discord webhook and huggingface /v1/models success reads from the original PR were superseded upstream by openclaw#98098 and openclaw#101079 (readProviderJsonResponse), so this branch now carries only the thread-ownership fix. Co-Authored-By: Claude <[email protected]> * fix(thread-ownership): bound forwarder conflict handling --------- Co-authored-by: Claude <[email protected]>
What Problem This Solves
discoverHuggingfaceModelsparsed the successful Hugging Face/v1/modelsresponse withresponse.json(). Node's Fetch body mixin consumes the complete response before parsing, so a runaway provider response could grow memory without a bound during provider-catalog discovery.Why This Change Was Made
The discovery owner now uses OpenClaw's shared
readProviderJsonResponse, which limits provider JSON bodies to 16 MiB, cancels the response stream on overflow, and labels malformed JSON errors. The surrounding discovery flow already catches provider failures and returns the bundled static model catalog, so oversized and malformed responses follow the established fail-open catalog behavior.The shared default is used directly instead of adding a second Hugging Face-specific copy of the same response-size policy.
User Impact
Hugging Face model discovery remains dynamic for normal responses and falls back to the bundled catalog if the provider sends malformed or unexpectedly large JSON. Authentication, routing, and the model-normalization path are unchanged.
Evidence
https://router.huggingface.co/v1/modelsas the OpenAI-compatible model-list endpoint.application/json, 81,363 bytes, 119 models; the production 16 MiB cap leaves substantial headroom.dda99df922200659c5126d1e453da70fba7b1aec: no accepted/actionable findings.