Skip to content

fix: preserve InvalidUploadSizeError through store/upload error chain (not "Network request failed") #841

Description

@BigLep

Summary

When a streaming upload fails because the packed piece/CAR is below the SP minimum size, the actionable InvalidUploadSizeError is buried under generic Network request failed / StorageContext store failed messages by the time it reaches SDK consumers (e.g. filecoin-pin CLI).

Users see an opaque network failure instead of the real size constraint.

Expected behavior

Consumers should receive (or be able to surface) the underlying InvalidUploadSizeError message, e.g.:

Invalid upload size.

Details: Size 125 bytes is below minimum allowed size of 127 bytes or exceeds maximum allowed size of ...

Actual behavior

filecoin-pin (and any SDK consumer displaying StoreError.message) shows something like:

Failed to store on primary provider 2 (https://calib2.ezpdpz.net)

Details: StorageContext store failed: Failed to store piece on service provider - Network request failed

The real cause is only visible by walking the nested cause chain (or with debug logging).

Error chain (observed)

  1. InvalidUploadSizeError — thrown in @filoz/synapse-core streaming upload when bytesUploaded < MIN_UPLOAD_SIZE (127 bytes) (upload-streaming.ts TransformStream.flush)
  2. NetworkErrorNetwork request failed (stream error during PUT to /pdp/piece/uploads/{uuid})
  3. Error via createError()StorageContext store failed: Failed to store piece on service provider - Network request failed (storage/context.ts)
  4. StoreErrorFailed to store on primary provider … with Details: taken from immediate cause message, not the deepest SynapseError (storage/manager.ts)

StoreError / SynapseError currently populate details from the immediate cause.message, so the useful InvalidUploadSizeError.details never surfaces.

How to reproduce

Via filecoin-pin (easiest end-to-end)

From a filecoin-pin checkout with calibration credentials (PRIVATE_KEY, etc. in .env):

# A lone `date` line packs to a ~125-byte CAR — below the 127-byte minimum.
TMPFILE=$(mktemp) && date > "$TMPFILE" && \
  LOG_LEVEL=debug NODE_DEBUG=fetch \
  npx tsx src/cli.ts add "$TMPFILE" --network calibration --provider-id 2

Observe:

  • User-facing failure: Network request failed
  • NODE_DEBUG=fetch shows HTTP 201 on POST …/pdp/piece/uploads, then failed PUT …/pdp/piece/uploads/{uuid} with Invalid upload size
  • Debug JSON log includes nested cause: InvalidUploadSizeError with full size details

Provider 2 (calib2.ezpdpz.net) ping succeeds; this is not connectivity.

Minimal SDK-level repro (conceptual)

Any synapse.storage.upload() / StorageContext.store() call with streaming body whose final size is < SIZE_CONSTANTS.MIN_UPLOAD_SIZE (127) against a provider enforcing that minimum should reproduce the wrapped error chain.

Suggested fixes (synapse layer)

Any of these (or a combination) would address the root cause:

  1. synapse-core: Do not wrap InvalidUploadSizeError in NetworkError when the upload stream fails on size validation; preserve the original error (or set it as cause on a typed error that retains details).
  2. synapse-sdk createError(): When wrapping, walk the cause chain for the deepest SynapseError and prefer its details / shortMessage in the outer message.
  3. StoreError construction (storage/manager.ts): When primary store() fails, attach root-cause details from the nested chain (similar to how SynapseError could be enhanced globally).

Fallback if this is rejected at the synapse layer

If maintainers prefer not to change synapse-sdk/synapse-core error propagation, the work should still be tracked in filecoin-pin (either move this issue there or open a sibling issue) to:

  • Walk the cause chain in CLI upload paths (add, import) — same pattern as existing describeLockupShortfall() for InsufficientLockupFunds
  • Surface known errors like InvalidUploadSizeError with actionable hints (e.g. pad test payloads past CAR overhead; see filecoin-pin DEVELOPMENT.md)

That would be a consumer-side workaround, not a root fix for other SDK users.

Context

Discovered while testing calibration uploads with filecoin-pin’s date > $TMPFILE one-liner. CAR overhead can push a tiny unique payload just under the SP minimum; the misleading network error made this hard to diagnose without LOG_LEVEL=debug + NODE_DEBUG=fetch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    🐱 Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions