Skip to content

createContentApiS3Signer falls back to legacy generateUploadUrl shape rejected by current engine #43

@vparys

Description

@vparys

Summary

createContentApiS3Signer silently falls back to the legacy generateUploadUrl mutation shape (top-level contentType/expiration/prefix/acl arguments) whenever the upload parameters carry none of suffix/fileName/extension — which is exactly what a default-configured S3UploadClient produces. Current Contember engine only accepts the input: S3GenerateSignedUploadInput envelope, so every default-configured upload fails.

Environment

Reproduction

const sign = createContentApiS3Signer(client)
// Default S3UploadClient parameters — nothing but the content type
// (S3UploadClient.upload builds { contentType: file.type, ...getUploadOptions?.(file) }):
await sign({ contentType: 'text/plain' })

The signer emits:

mutation($contentType_0: String, $expiration_0: Int, $prefix_0: String, $acl_0: S3Acl) {
  url_0: generateUploadUrl(contentType: $contentType_0, expiration: $expiration_0, prefix: $prefix_0, acl: $acl_0) { ... }
}

which engine 2.1.0-alpha.39 rejects — verified directly against the Content API:

  • envelope form generateUploadUrl(input: $i)200, signed URL returned
  • legacy form above → error ("ACL is not supported" UserInputError; environments without the S3Acl scalar fail earlier with "Unknown type S3Acl" / "Cannot query field generateUploadUrl")

Expected behavior

The signer always requests the URL via generateUploadUrl(input: S3GenerateSignedUploadInput) — the only shape the current engine supports, and the same shape the signer already uses when fileName/suffix/extension happen to be present.

Actual behavior

packages/bindx-uploader/src/utils/urlSigner.ts branches on

const hasNewFormat = params.suffix || params.fileName || params.extension

and builds the legacy top-level-arguments mutation when none of those optional fields is set. A default-configured S3UploadClient (no getUploadOptions) therefore never uploads: the engine rejects the whole mutation. In batched mode a single legacy alias poisons the entire batch even when other aliases use the envelope.

Suspected root cause

packages/bindx-uploader/src/utils/urlSigner.ts, buildGenerateUploadUrlMutation — the hasNewFormat heuristic conflates "caller provided new-format-only fields" with "server supports the new format". The legacy branch predates the engine's switch to the input envelope and is dead weight against current engines.

Suggested fix

Always build the envelope form and drop the legacy branch (the envelope carries all legacy fields too — contentType/prefix/expiration/acl are members of S3GenerateSignedUploadInput). If compatibility with pre-envelope engines is still required, gate on an explicit option rather than on the presence of unrelated per-file fields.

Workaround shipped downstream

We applied a temporary workaround in our project, marked TODO [BindX] (<this-issue-url>): …. The workaround passes getUploadOptions: file => ({ fileName: file.name }) to S3UploadClient so hasNewFormat is always true; we will remove it once this issue is resolved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions