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. NetworkError — Network 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. StoreError — Failed 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.

Activity

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

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