Troubleshooting
This page is for the operator of a function-wasm pod and for the module author whose module the runtime refuses. Find the message in the pod’s logs, in a step’s fatal result or in the output of function validate or guestfn, then follow the entry. Entries are grouped by what failed and match the current release. Each quoted message is a prefix or a fragment: match on the part that doesn’t vary.
Module load
cannot instantiate module: trap: …: the guest trapped while the runtime instantiated it, such as by panicking in its start-up code. The stack is in the function pod’s stderr.component does not implement the wasmfn:function@2.0.0 world: …: the component doesn’t typecheck againstwit/wasmfn-function.wit: it has norunexport (no exportrunfound) or imports something the runtime doesn’t provide. Rebuild against the currentwit/, and useguestfn inspect fn.wasmto list what the module exports and imports.cannot load module …: cannot compile module: failed to parse WebAssembly module: threads support is not enabled, or the same for another proposal: the module uses a WebAssembly proposal the engine refuses: threads, GC, function references, exceptions, tail calls, multi-memory or memory64 (ABI v2 lists what it accepts). Build the guest without that feature, which no scaffold’s toolchain emits by default.cannot load module …: module is a core module, which function-wasm 1.0.0 no longer runs (ABI v1 was removed); build it as an ABI v2 component (docs/abi-v2.md): rebuild the guest as a component. For a Go guest,guestfn buildturns the core module thatgo buildemits into one; a guest written for ABI v1 is rebuilt on a current scaffold (guestfn init, then move the function over).guestfn inspectandfunction validate --resolveprint the same sentence.built fn.wasm, but the runtime would refuse it: …fromguestfn build, or a refusal fromguestfn push: the message is the runtime’s own load-time refusal. The entries before this one cover the common ones.module.oci.ref … tags are not supported: pin the reference to the manifest digest,repo@sha256:…orrepo:tag@sha256:…, asguestfn pushprints it.module layer is a tar archive without /fn.wasm: aFROM scratchimage mustCOPYthe module to/fn.wasm. Preferguestfn pushororas push, which write a rawapplication/wasmlayer.
Input and admission
function validate runs the same checks as the runtime. Run it with the flags you start the runtime with: exit 1 means a step is refused and the line states the reason, and exit 2 means the tool itself failed. The fields are in the Input reference.
module.path is refused: the runtime was started without--module-dir.module.from: … names a OCI source, but the Input has no compositionPolicy: amodule.fromsource that isn’t static needs acompositionPolicywhosepullModulepermits its repository. Add the policy or make the source static.module.from: cannot read status.module from the composite resource: module: no such field: the composite resource hasn’t set the field the step reads. Set it, or addmodule.allowEmpty: trueso the step runs nothing until it’s set. The pod logs the skipped step. See Metrics.module.allowEmpty is set but module.from is not:allowEmptyapplies only to a field the composite resource may leave unset. Remove it, or switch the step tomodule.from.apiVersion wasm.fn.crossplane.io/v1beta1 is deprecated and is removed in function-wasm 2.0.0; write apiVersion: wasm.fn.crossplane.io/v1 (the same fields): a warning fromfunction validateandguestfn build, and a log line per request. Change theapiVersionline.limits.memory 1Gi exceeds the runtime's --module-memory-limit of 512Mi, or the same forlimits.timeoutand--module-timeout: lower the limit or raise the flag.module oci … has an invalid manifest: config.schema: Resource '…' is not present in a registry and retrieving it failed: $ref … is external; config.schema must be self-contained: the module’sconfig.schemareferences a URL or a file. The runtime never fetches a reference. The author inlines the referenced schema. A#/$defs/…reference inside the schema is fine.module oci … config does not match the module's schema: /greeting: got number, want string: the Input’sconfigfails the module’sconfig.schema.
Policy grants
The layers are explained in Cedar policy, and the operator’s side in Grant policy.
-
module oci … requires egress GET to host "x" (requires.egress.http[0]), which the operator policy (--sandbox-policy-file) does not permit: the manifest requests a capability that the layer named in the message doesn’t permit. Variants:… which the compositionPolicy does not permit: the composition layer refuses it.module … requires a private /tmp (requires.filesystem.privateTmp), but the runtime has no --sandbox-policy-file, which is required to grant sandbox capabilities, and the same for env and egress: the runtime has no policy file at all.module oci … requires credential "cmdb" (requires.credentials[0]), which the operator policy (--sandbox-policy-file) does not permit, or… but the runtime has no --sandbox-policy-file, which is required to grant step credentials (spendCredential): the layer has nospendCredentialpermit forCredential::"cmdb".requires runtime vX or newer, this is vY: the module needs a newer runtime.
Add a
permitto the layer named, or mount a policy file. A module that requests less avoids the refusal. -
A module stops seeing a step credential it used to read: the runtime forwards only the credentials a module was granted. Declare it in the manifest, with
requires.credentials: [name]for the whole credential or arequires.envbinding for one key. Then permitspendCredentialfor it in the operator policy, and in acompositionPolicythat scopes the action.function validate --resolvelists what each step’s module receives, and the runtime logs the withheld names at debug level. See Module manifests. -
module … requires.credentials[0]: the request carries no credential "cmdb"; declare it on the pipeline step: add the credential to the step’scredentials. -
the operator policy grants a private /tmp (usePrivateTmp), but the runtime cannot create one under …at startup: pointTMPDIRat a writable directory. AnemptyDirwith asizeLimitalso bounds what a module may write. -
A guest gets
EPERMunder/tmp: the path is outside the private/tmp, the only directory the guest has. -
operator policy …: dialAddress rule "…" must scope the action as == Action::"dialAddress", or another Cedar load error: the--sandbox-policy-fileis malformed and refused at load. AdialAddresscondition accepts onlycontext.ip.isInRange(ip("CIDR")),context.ip.isLoopback()or a||of them. -
module oci …: composed apps/Deployment "deployment" (modify), which the compositionPolicy does not permit (composeResource), or… which the operator policy (--sandbox-policy-file) does not permit …, or… composed platform.example.org/WebApp (composite, modify), which …: the module changed a resource that nopermitof the scoped layer matches, and the runtime applied none of its output. Widen the layer named or use a module that composes less. The rules are in the Cedar policy reference. -
module oci …: composed resource "thing" states no apiVersion or kind, so the policy layers cannot judge it (composeResource): a resource the module returned indesired.resourceshas noapiVersionorkindstring. Fix the module.
Signatures
Signing, keyless verification and the trusted root are explained on the Signatures page.
cannot verify module oci …: the operator policy requires a cosign signature, but the runtime has neither --cosign-key nor --cosign-trusted-root to verify it: add--cosign-key. For keyless signatures add--cosign-trusted-rootand atrustSignerrule instead. Or narrow therequireSignaturerule.cannot verify module oci …: <ref> carries no cosign signature (no Sigstore bundle among its referrers): none of the manifest’s OCI 1.1 referrers is a Sigstore bundle whose subject is this digest. Sign the module with cosign 3. A module signed only with cosign 2 or with--new-bundle-format=false(asha256-<hex>.sigtag) lands here too: the legacy format isn’t read, so re-sign it.cannot verify module oci …: no valid cosign signature for <ref>: signature does not verify with the configured keys: a bundle exists but no--cosign-keykey signed it. The same list also reportssigned statement's predicate type is "https://slsa.dev/provenance/v1", not https://sigstore.dev/cosign/sign/v1(an attestation),signed statement is for another digestand bundle fetch, size or digest failures.… keyless signature cannot be verified: the runtime has neither --cosign-trusted-root nor --cosign-trust-instance: the signature is keyless. Add--cosign-trusted-rootor--cosign-trust-instance public-good, and atrustSignerrule for the signer. The reverse,key-based signature cannot be verified: the runtime has no --cosign-key, means a key-based bundle met a runtime with only a trusted root.… keyless signature cannot be verified: the trusted root of <instance> has not been fetched yet (the last attempt failed: …):--cosign-trust-instanceis set and every fetch has failed. The message quotes the last failure. The runtime retries every minute and admits the module once a refresh succeeds, which the log reports asTrusted root updated. For a pod without network, mount the root with--cosign-trusted-root.--cosign-trusted-root and --cosign-trust-instance are mutually exclusive: the file is the trusted root, or the instance's root is fetched over TUFat startup, or--cosign-tuf-refresh must be at least 1m0s: choose the file for an air-gapped pod and the instance for one that can fetch.… keyless signature does not verify against the trusted root: <reason>: the runtime refused the bundle, and the reason is the verification library’s own text. Typical causes are a signature made under a different Sigstore instance, an invalid signature or log promise, or a bundle with neither a Rekor entry nor an RFC 3161 timestamp. Runcosign verifywith the certificate identity and issuer against the same root to tell which.… keyless signature by <identity> (issuer <issuer>) is not trusted for <repository>: no trustSigner rule in the operator policy permits it: the signature verifies but notrustSignerrule covers that signer for the repository. Add or widen a rule for the identity and issuer.
Egress
Egress is explained on the HTTP egress page.
sandbox.egress: <host> resolves to an address the egress policy blocks: the host refuses private, loopback, link-local and cluster ranges by default. Add the range to the policy’sallowedCIDRsto permit an in-cluster service.sandbox.egress: HTTP egress is not granted to this module: its manifest requires no egress (requires.egress.http): the module made an HTTP request but its manifest doesn’t require egress. Addrequires.egress.httpto the manifest. A Go guest sees the message prefixed withwasmfn:.sandbox.egress: the module's request rate exceeds the egress policy's rateLimit: raise--egress-rate-limit-per-minuteand--egress-rate-limit-burst, or reduce the module’s request frequency.
Runtime and startup
cannot create cache directory /tmp/function-wasm-cache: …at startup: the pod’s filesystem is read-only there. Mount anemptyDirat that path through aDeploymentRuntimeConfig.module … failed: waiting for a run slot: deadline exceeded, or the step-slot and run-memory forms: the request’s deadline passed while it waited for a bound, so nothing ran. Raise the bound, shorten runs, or watchfunction_wasm_module_runs_in_flight(see Metrics).cannot load module … : compile exceeded --module-compile-timeout 5m0s: a cold load (fetch and compile) ran past the bound. The compile finishes on its own and stores its artifact, so the next request for that digest is served; a module that hits the bound every time is too large to compile under it, so raise the bound or lower--max-module-size.- The first request is slow, later ones are fast: expected, because the compile happens once per module digest per process. A volume under
/tmp/function-wasm-cachespares the next process the fetch, not the compile, which--warm-modulesmoves ahead of readiness. See the cache section of Runtime flags. Cannot warm moduleat startup: a--warm-modulesentry didn’t load, and the log line gives the entry and the reason. The pod serves anyway and loads that module on its first request.- The readiness probe fails for a while after start: the pod is warming
--warm-modules. See Readiness.