Skip to content

[Bug]: Local Lambda HTTP service rejects DurableExecutionArn / CallbackId containing "/" #9039

Description

@yaythomas

Description

samcli/local/lambda_service/local_lambda_http_service.py registers Flask routes with the default <string> URL converter:

"/2025-12-01/durable-executions/<durable_execution_arn>"
"/2025-12-01/durable-executions/<durable_execution_arn>/history"
"/2025-12-01/durable-executions/<durable_execution_arn>/stop"
"/2025-12-01/durable-execution-callbacks/<callback_id>/succeed"
"/2025-12-01/durable-execution-callbacks/<callback_id>/fail"
"/2025-12-01/durable-execution-callbacks/<callback_id>/heartbeat"

The <string> converter does not match /. After aws-durable-execution-sdk-python-testing#216, DurableExecutionArn values are minted as <uuid>/<invocation-id> and boto percent-encodes the / as %2F in the URI label. Werkzeug decodes %2F back to / during routing, so the path no longer matches a single <string> segment and the request 404s before reaching the handler:

botocore.exceptions.ClientError: An error occurred (PathNotFoundLocally) when calling
the GetDurableExecutionHistory operation: PathNotFoundException

The same shape applies to base64-encoded CallbackId values, which contain /.

Failing tests

local-start-lambda job in Integration Tests #8779:

  • tests/integration/local/start_lambda/test_start_lambda_durable.py::TestStartLambdaDurable::test_local_callback_cli_fail_{0,1,2}
  • …test_local_callback_cli_heartbeat
  • …test_local_start_lambda_invoke_durable_function_{HelloWorld,MapOperations,NamedStep,NamedWait,Parallel}
  • …test_local_start_lambda_invoke_timeout
  • …test_local_start_lambda_invoke_wait_for_callback_{success,failure}_{cli,http}*

All fail with PathNotFoundLocally on GetDurableExecutionHistory, GetDurableExecution, or StopDurableExecution. Reproduced locally on develop.

Fix

Use Werkzeug <path:...> converters for the ARN/callback URI labels. <path> accepts / and Werkzeug picks the right rule via trailing-literal specificity (verified with a Flask test client: …/<path:arn>/history wins over …/<path:arn> for …/abc%2Fdef/history). Existing unquote() calls in handlers can stay — idempotent on already-decoded values. Backwards-compatible with old UUID-only paths.

Activity

  1. added 2 commits that reference this issue on May 21, 2026
    1556d11
    d45a481
  2. github-actions commented on May 21, 2026

    @github-actions
    Contributor

    ⚠️COMMENT VISIBILITY WARNING⚠️

    Comments on closed issues are hard for our team to see.
    If you need more assistance, please either tag a team member or open a new issue that references this one.
    If you wish to keep having a conversation with other community members under this issue feel free to do so.

  3. added a commit that references this issue on May 21, 2026
    d97adde
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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions