Skip to content

[plugin] lambda-build and lambda-deploy can disagree on target architecture (latent broken-function bug) #683

Closed

Description

@sebsto

Summary

lambda-build and lambda-deploy disagree about the target architecture, and nothing enforces consistency. This lets a user build for one architecture and deploy a function declaring the other, producing a function that fails to run — with no error at build or deploy time.

Details

  • lambda-build has no --architecture flag. The cross-compile container runs under the host/daemon's default architecture, and the produced binary's architecture is whatever the base image resolves to. There is no way to select it explicitly and no record of what was built.
  • lambda-deploy does have --architecture, defaulting to Architecture.host (#if arch(x86_64) → x64, else arm64), and passes it to CreateFunction.architectures.

Because the two sides choose the architecture independently, a mismatch is possible today — e.g. build produces an arm64 binary while deploy declares x64 (or the reverse if building on one host and deploying from another). The deployment "succeeds" but the function is broken at invoke time. The failure is latent: neither plugin validates that the deployed architecture matches the built binary.

Expected

  • lambda-build should accept --architecture <x64|arm64> (default: host) and build for that architecture explicitly (docker --platform linux/<arch>, Apple container --arch <arch>).
  • The built architecture should be recorded and consumed by lambda-deploy so its --architecture defaults to what was actually built, rather than independently defaulting to the host.
  • A mismatch between an explicitly-requested deploy architecture and the built artifact should be a hard error, not a silently broken function.

Notes

This was discovered while designing OCI image support (where the image's single architecture is baked in and must match CreateFunction.architectures, making the mismatch fatal rather than latent). A build→deploy metadata handoff (e.g. a build manifest recording architecture) would address both this and the OCI case. Tracking the underlying architecture-consistency bug here independently of OCI.

Activity

  1. added theissue type on Jun 29, 2026
  2. sebsto commented on Jun 29, 2026

    @sebsto
    CollaboratorAuthor

    Note on history: this is not a regression introduced by the v2 plugin rewrite (#567). The legacy archive/packager plugin never had a build-side --architecture flag either — it only had --swift-version / --base-docker-image and never passed --platform to docker, so it always built for the Docker daemon's default architecture.

    The deploy-side architecture parameter has existed independently since Jan 2023 (commit f3f4021, in the old Deploy.swift deployment descriptor), feeding CreateFunction.architectures. So the build-vs-deploy asymmetry is original to the plugins, not something lost in #567 — this issue closes a long-standing gap rather than restoring removed behaviour.

  3. sebsto commented on Jul 1, 2026

    @sebsto
    CollaboratorAuthor

    Rescoping this after the OCI PR (#687), which built the build-manifest hand-off but only wired it into the image path.

    Current state against the three expected items:

    1. --architecture flag on lambda-build: still missing. Both backends hardcode .host (ZipArchiveBackend.swift, and makeArchiveBackend() which has a comment pointing back here).
    2. Recorded and consumed by deploy: half done. The manifest records architecture, and the image deploy path reads it (Deployer+ECR.swift). But the ZIP deploy path still ignores it and uses configuration.architecture, which independently defaults to host (Deployer+Zip.swift). Since ZIP is the default format, the original latent mismatch is still fully present.
    3. Hard error on mismatch: not done. Deploy guards package-type immutability but never compares manifest.architecture to the requested deploy architecture.

    So the OCI-fatal case is handled, but the underlying latent ZIP bug this issue tracks is not. Remaining work:

    • add --architecture <x64|arm64> to lambda-build (default host), write it into the ZIP manifest instead of .host
    • have deployZip default its architecture to manifest.architecture
    • make an explicit deploy --architecture that disagrees with the manifest a hard error
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

    good first issueGood for newcomerskind/bugFeature doesn't work as expected.size/SSmall task. (A couple of hours of work.)🔨 semver/patchNo public API change.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions