Skip to content

storage: the presigned-upload door answers 500 INTERNAL for a non-numeric size and accepts a negative size #27413

Closed

Description

@objectstack-fleet

domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB

QA-source: #27409 · attachments-storage.presigned-upload-roundtrip · observed beside the clauses

Found by an off-clause probe (size boundary values) in the 18.3.0 release-candidate QA run #27409, at framework c4c515ad, on the stock showcase. Signed in through the form.

Reproduction

  1. As admin, POST /api/v1/storage/upload/presigned with {"filename":"a.png","mimeType":"image/png","size":"abc"}. It answers 500 INTERNAL, and the server log reads Insert operation failed sys_file "Size (bytes) must be a number".
  2. The same request with "size": -5 answers 200, and a pending sys_file row is stored with size: -5.

Expected vs actual

  • Expected: 400 INVALID_REQUEST for a size that is not a non-negative finite number, with no row written. A 500 tells an operator the server is broken when the client sent a bad value.
  • Actual: 500 for "abc", and 200 with a negative-size row for -5.

Mechanism

  • packages/services/service-storage/src/storage-routes.ts (around lines 916 to 930) checks only size == null, then calls requireWithinUploadLimit(Number(size)). That lets NaN and negative values through.
  • For NaN, the engine's field validation throws at insert, and the route's catch maps that to 500.
  • For a negative value, nothing refuses it.

Suggested acceptance

  • "abc", -5, NaN, and "" each answer 400 naming size, and no sys_file row is written.
  • 0 and a valid positive size behave as today.
  • A pin is added beside storage-routes.test.ts.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 文件 | none | P②

    Triage: p2 · domain:server · area:files · 2026-10-29T06:02Z

    ⛔ Not a claim.

    • Read fresh. The presigned-upload door answers 500 for a non-numeric size and stores a negative one. A bad input should get a 400 with no row written. As it stands, the door stores wrong data and points operators at the server, so p2.
    • ⛔ Use the door's own refusal envelope (ADR-0112): 400, with the field named.
    • It is extracted from the 18.3.0 RC run, so it is listed in wave anchor [sweep] v18.3.0 release test sweep #27377 §5 by the runner, and it is retested on the next wave.
    • bug, pm:queue.

    Generated by Claude Code

  2. added
    area:filesFiles — upload, download, signed URLs, access derived from the parent record
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 29, 2026
  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB

    Path: 文件 | none | P②

    Triage: lands in packages/services/service-storage/src/storage-routes.ts (domain:server); rationale: this concurs with the first touch at 06:02Z (comment 6489280043). Labels stay as they are (bug, priority:p2, pm:queue, area:files, domain:server). This note adds the parts of the first touch that the duties require and that were missing. Read at origin/main ded67bfb, 2026-10-29T09:55Z.

    Fold suggestion (the execution seat decides): fold with #27412, for the same file and the same class of validation; see the note there. Draft PR #27424 does not touch storage-routes.ts, so it is disjoint.

    Size/model suggestion: S.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB

    Claim: PM loop round 1
    Session: session_017xRBcScm27Q3R5mkYLPWdB
    Account: sunhaolin
    Branch: claude/issue-27412-storage-route-input
    Worktree: objectstack-issue-27413
    Domain: domain:server
    Seat: domain:devx#1
    File surface: as on #27412 (one branch for the fold): storage-routes.ts presign size check, its tests, the same changeset (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default (dispatch-gates --tier at c4c515a: "no path-derived mandate"), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: service-storage route code: requireWithinUploadLimit(Number(size)) lets NaN and negatives through | no platform path covers it | reached by any signed-in uploader
    Thread-read: 6494074046
    Premise: holds (triage first touch re-verified the mechanism on origin/main ded67bfb; the dev re-measures before editing)
    Serial constraints cleared: see #27412 (chain head); none

    Maintainer direct dispatch (cross-lane claim authority): the maintainer, in session session_017xRBcScm27Q3R5mkYLPWdB on 2026-10-29, verbatim: 「你应该使用 pm-dispatch 技能处理 issue 和 pr」. This devx-seat session claims these domain:server cards on that instruction; the card stays domain:server.
    Fold member of the #27412 family dispatch: branch claude/issue-27412-storage-route-input, the full serial-constraint check and the five fold gates are on #27412.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB

    ACCEPT → PR #27537 (head 41272f9f, contract review PASS 6496658225), reviewed 2026-10-29T12:29Z. Ready to land, held on the landing permission. Follow-up for the sibling init door and the spec size: #27549.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB

    Handover: PR #27537 → PM session session_017xRBcVy4VXmkQjn2MGeaWk (review and landing)


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:filesFiles — upload, download, signed URLs, access derived from the parent recordbugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions