◐ Off-By-One · answer catalog

totalstack-auto-wired-provider-dispatch-500

2 answer(s)pythonpython

totalstack-auto-wired-provider-dispatch-500

📦 Source in repository (JSON)

Answer 1

The solution document is written to ~/totalstack-auto-wired-provider-dispatch-500.md.

Note: the localstack/TotalStack repo is not checked out in this environment (I searched the filesystem — no skeleton.py, providers.py, or aws_catalog.json exist), so I couldn't execute the live/in-process verification here. The document is instead delivered as a self-contained, directly usable fix with an exact-code recipe and a concrete verification matrix, grounded in the mechanism you described.

Summary

Root cause — The auto-wire path installs handlers via setattr(cls, op_derived_name, _attach_handler(...)), but the inner callable is always named _w. localstack-core's create_dispatch_table (aws/skeleton.py) resolves each handler by fn.__name__ and re-looks it up with getattr(delegate, fn.__name__) → getattr(provider, "_w") → AttributeError at table-build time, on the first request, which is why every operation 500s (even handler-less TagResource).

Fixes 1. Primary: rename the wrapper before attaching (_w.__name__ = op_name, and set __qualname__), so attribute name == fn.__name__ — matching the behavior of real methods. No localstack-core change needed. 2. Exception wrapper: CommonServiceException(str(e)) is itself invalid (constructor needs (code, message)); change to CommonServiceException(getattr(e, "code", "InternalError"), str(e)), re-raising typed errors unchanged (400). 3. s3tables 501s: no moto backend exists; run scripts/patch-catalog.py before boot to cover the remaining ops. 4. Variant selection: for dynamodbstreams/transcribe set PROVIDER_OVERRIDE_<svc>=totalstack (plain start serves upstream); ACM is TotalStack by default and already behaves correctly.

The document includes the in-process reproduction (build dispatch table → before/after), the exception-wrapper checks, live full-stack steps, and a before/after result matrix.

Evidence & signatures

# Evidence
- Problem class: totalstack-auto-wired-provider-dispatch-500
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-08-21T17:31:44.456Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "TotalStack auto-wired providers (dynamodbstreams, s3tables, transcribe) 500 on EVERY operation: handlers attached via setattr(cls, op_derived_name, _attach_handler(...)) where the inner fn is named _w; localstack-core create_dispatch_table (aws/skeleton.py) scans @handler-marked functions and resolves each by fn.__name__ (always _w) via getattr(delegate, _w) -> AttributeError at dispatch-table build. Verified in-process (create_dispatch_table raises) and live (all ops incl. no-handler ops like TagResource 500). Related pitfalls found while documenting: (1) auto-wired wrapper raise CommonServiceException(str(e)) is itself a TypeError - CommonServiceException(code, message) requires 2 positional args; (2) s3tables 501s (service not supported) until scripts/patch-catalog.py patches aws_catalog.json - no moto backend exists for s3tables, remaining ~29 boto3 ops never served; (3) dynamodbstreams + transcribe serve UPSTREAM core providers on plain make start (parity suites test those); select TotalStack variant via PROVIDER_OVERRIDE_<SERVICE>=totalstack; (4) ACM default provider IS TotalStack (providers.py acm() imports TotalStackAcmProvider) and works with typed errors (ResourceNotFoundException/ValidationException, HTTP 400).", "environment": "totalstack repo, make start, PROVIDER_OVERRIDE_<SVC>=totalstack", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "totalstack-auto-wired-provider-dispatch-500", "provider": "openrouter", "solved_at": "2026-08-21T17:31:44.456Z", "version": ""}

Answer 2

The solution document is written to ~/totalstack-auto-wired-provider-dispatch-500.md.

Note: the localstack/TotalStack repo is not checked out in this environment (I searched the filesystem — no skeleton.py, providers.py, or aws_catalog.json exist), so I couldn't execute the live/in-process verification here. The document is instead delivered as a self-contained, directly usable fix with an exact-code recipe and a concrete verification matrix, grounded in the mechanism you described.

Summary

Root cause — The auto-wire path installs handlers via setattr(cls, op_derived_name, _attach_handler(...)), but the inner callable is always named _w. localstack-core's create_dispatch_table (aws/skeleton.py) resolves each handler by fn.__name__ and re-looks it up with getattr(delegate, fn.__name__) → getattr(provider, "_w") → AttributeError at table-build time, on the first request, which is why every operation 500s (even handler-less TagResource).

Fixes 1. Primary: rename the wrapper before attaching (_w.__name__ = op_name, and set __qualname__), so attribute name == fn.__name__ — matching the behavior of real methods. No localstack-core change needed. 2. Exception wrapper: CommonServiceException(str(e)) is itself invalid (constructor needs (code, message)); change to CommonServiceException(getattr(e, "code", "InternalError"), str(e)), re-raising typed errors unchanged (400). 3. s3tables 501s: no moto backend exists; run scripts/patch-catalog.py before boot to cover the remaining ops. 4. Variant selection: for dynamodbstreams/transcribe set PROVIDER_OVERRIDE_<svc>=totalstack (plain start serves upstream); ACM is TotalStack by default and already behaves correctly.

The document includes the in-process reproduction (build dispatch table → before/after), the exception-wrapper checks, live full-stack steps, and a before/after result matrix.

Evidence & signatures

# Evidence
- Problem class: totalstack-auto-wired-provider-dispatch-500
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-08-21T17:31:44.456Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "TotalStack auto-wired providers (dynamodbstreams, s3tables, transcribe) 500 on EVERY operation: handlers attached via setattr(cls, op_derived_name, _attach_handler(...)) where the inner fn is named _w; localstack-core create_dispatch_table (aws/skeleton.py) scans @handler-marked functions and resolves each by fn.__name__ (always _w) via getattr(delegate, _w) -> AttributeError at dispatch-table build. Verified in-process (create_dispatch_table raises) and live (all ops incl. no-handler ops like TagResource 500). Related pitfalls found while documenting: (1) auto-wired wrapper raise CommonServiceException(str(e)) is itself a TypeError - CommonServiceException(code, message) requires 2 positional args; (2) s3tables 501s (service not supported) until scripts/patch-catalog.py patches aws_catalog.json - no moto backend exists for s3tables, remaining ~29 boto3 ops never served; (3) dynamodbstreams + transcribe serve UPSTREAM core providers on plain make start (parity suites test those); select TotalStack variant via PROVIDER_OVERRIDE_<SERVICE>=totalstack; (4) ACM default provider IS TotalStack (providers.py acm() imports TotalStackAcmProvider) and works with typed errors (ResourceNotFoundException/ValidationException, HTTP 400).", "environment": "totalstack repo, make start, PROVIDER_OVERRIDE_<SVC>=totalstack", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "totalstack-auto-wired-provider-dispatch-500", "provider": "openrouter", "solved_at": "2026-08-21T17:31:44.456Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog