Skip to content

Implement Lambda runtime init error reporting#103

Draft
joe4dev wants to merge 2 commits into
localstack-api-compat-testfrom
devx-1-implement-lambda-runtime-init-error-reporting
Draft

Implement Lambda runtime init error reporting#103
joe4dev wants to merge 2 commits into
localstack-api-compat-testfrom
devx-1-implement-lambda-runtime-init-error-reporting

Conversation

@joe4dev
Copy link
Copy Markdown
Member

@joe4dev joe4dev commented Jun 3, 2026

Summary

When a Lambda runtime exits unexpectedly or throws an error during initialization, LocalStack previously received no callback and would wait until the environment timeout. This PR adds two complementary error-reporting paths so LocalStack immediately receives a structured ErrorResponse instead of timing out.

Changes

cmd/localstack/supervisor.go — new

LocalStackSupervisor wraps the sandbox's ProcessSupervisor and intercepts process termination events on a background goroutine. When a runtime-* process exits and the runtime is not already shutting down intentionally, it constructs a FaultData with fatalerror.RuntimeExit and calls eventsAPI.SendFault(). An atomic isShuttingDown flag (set on Terminate/Kill, cleared on Exec) prevents duplicate fault events during graceful restarts.

cmd/localstack/events.go — new

LocalStackEventsAPI wraps telemetry.StandaloneEventsAPI and overrides SendFault to forward runtime faults to LocalStack as error status callbacks. It embeds the requestId in the error message and tracks the current invoke ID (thread-safe via sync.RWMutex) for faults that originate outside of an active invocation.

cmd/localstack/custom_interop.go — modified

  • ErrorResponse.RequestId changed from string to *string with omitempty: a pointer-to-empty-string serializes as "" (required by LocalStack's init error contract), while nil (used in fault events) is omitted.
  • NewCustomInteropServer now accepts a pre-created *LocalStackAdapter instead of constructing one internally, so the adapter is shared with the events API.
  • SendInitErrorResponse now parses the raw error payload from the runtime, enriches it with the current invoke ID, and asynchronously POSTs the structured response to LocalStack /status/{runtime_id}/error before propagating to the delegate. Falls back to the raw payload if parsing fails.

cmd/localstack/main.go — modified

LocalStackAdapter is created once upfront and passed to both NewLocalStackEventsAPI and NewCustomInteropServer. The sandbox is configured with SetEventsAPI(lsEventsAPI) and SetSupervisor(localStackSupv). The supervisor's context is cancelled in the existing shutdown func alongside the file watcher.

Tests

Covered by the integration tests in localstack/localstack-pro#7293:

Scenario Test
Exception raised during module import test_lambda_runtime_error
sys.exit() called during init test_lambda_runtime_exit
Missing AWS_LAMBDA_EXEC_WRAPPER script test_lambda_runtime_wrapper_not_found

Related

Depends on #101
Closes DEVX-1

joe4dev and others added 2 commits June 3, 2026 18:14
…s API

Ports the supervisor and events API from PR #41 to enable proper error
reporting when a Lambda runtime process exits unexpectedly (e.g. sys.exit()
or missing wrapper script), instead of LocalStack timing out with a generic
error.

- Add LocalStackSupervisor: wraps ProcessSupervisor, detects unexpected
  runtime-* process exits and emits SendFault(RuntimeExit) events
- Add LocalStackEventsAPI: wraps StandaloneEventsAPI, overrides SendFault
  to forward errors to LocalStack via SendStatus(error, ...)
- Wire both into SandboxBuilder via SetEventsAPI / SetSupervisor
- Refactor NewCustomInteropServer to accept a pre-created *LocalStackAdapter
  shared with the events API
- Improve SendInitErrorResponse: properly deserialises the payload, includes
  RequestId, and sends asynchronously (non-blocking)

Enables test_lambda_runtime_exit and test_lambda_runtime_wrapper_not_found.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use *string for the RequestId field in ErrorResponse so that an empty
string is serialized (not omitted by omitempty), while nil — used for
fault events — stays omitted. Fixes test_lambda_runtime_error snapshot
mismatch where requestId: "" was expected but absent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant