Skip to content

fix(event-handler): preserve original string for invalid Bedrock Agent number params#5363

Open
kimnamu wants to merge 1 commit into
aws-powertools:mainfrom
kimnamu:fix/bedrock-agent-number-param-fallback
Open

fix(event-handler): preserve original string for invalid Bedrock Agent number params#5363
kimnamu wants to merge 1 commit into
aws-powertools:mainfrom
kimnamu:fix/bedrock-agent-number-param-fallback

Conversation

@kimnamu

@kimnamu kimnamu commented Jun 19, 2026

Copy link
Copy Markdown

Summary

First, thank you to the maintainers for Powertools for AWS Lambda — it makes building Lambda functions a pleasure, and the cross-runtime parity work is much appreciated.

This is a small follow-up to that alignment effort. The BedrockAgentFunctionResolver coerces number/integer parameters with Number(param.value) unconditionally. When a Bedrock Agent sends a number/integer-typed parameter whose value is not a valid numeric string, Number(...) returns NaN, which serializes to null via JSON.stringify — the original value sent by the agent is silently lost.

The Python runtime already guards against this: it wraps int()/float() in try/except and falls back to the original string (bedrock_agent_function.py at L212-L221). This PR carries the same fallback over to the TypeScript resolver, so the two runtimes behave consistently.

Changes

packages/event-handler/src/bedrock-agent/BedrockAgentFunctionResolver.ts — for the number/integer case, fall back to the original string when Number(...) yields NaN:

case 'number':
case 'integer': {
  const parsed = Number(param.value);
  // Fall back to the original string when the value is not a valid
  // number (e.g. `Number('abc')` is `NaN`, which serializes to `null`).
  // This matches the behavior of the Python runtime.
  toolParams[param.name] = Number.isNaN(parsed) ? param.value : parsed;
  break;
}

This is the minimal change required: it touches only the NaN branch and leaves every other path untouched.

Before / After

Tool that echoes back a number-typed parameter with value 'not-a-number':

Case Before After
number/integer param, non-numeric value ('not-a-number') NaN → response body null (value lost) ✅ original string "not-a-number" preserved (matches Python)
number/integer param, valid value ('42') 42 42 (unchanged)
boolean / string / array params ✅ unchanged ✅ unchanged
Public API / method signatures / valid-number behavior ✅ unchanged

Issue number: Closes #5362

This continues the Bedrock Agent Function resolver alignment effort, which was previously tracked under the resolver parity work released in v2.21.0.

Testing

Added a parametrized regression test (it.each(['number', 'integer'])) in packages/event-handler/tests/unit/bedrock-agent/BedrockAgentFunctionResolver.test.ts asserting the original string is preserved.

Green (with fix):

✓ tests/unit/bedrock-agent/BedrockAgentFunctionResolver.test.ts (24 tests)
 Test Files  1 passed (1)
      Tests  24 passed (24)

Red (fix reverted via git stash, new test kept) — proves the test catches the bug:

 FAIL  ... > preserves the original string when a 'number' parameter is not a valid number
 FAIL  ... > preserves the original string when a 'integer' parameter is not a valid number
AssertionError: expected 'null' to deeply equal '"not-a-number"'
Expected: ""not-a-number""
Received: "null"
      Tests  2 failed | 22 passed (24)

Local gates:

  • npx biome lint on both changed files → clean.
  • Coverage on the changed file: Statements 100% (33/33), Branches 100% (23/23), Functions 100% (4/4), Lines 100% (33/33) — the new branch is fully covered.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

This contribution was prepared with the help of an AI agent (Claude Code); a human reviewed the change, the rationale, and the test results before submitting.

…t number params

The BedrockAgentFunctionResolver unconditionally coerced `number`/`integer`
parameters with `Number(param.value)`, producing `NaN` (serialized to `null`)
when the value is not a valid number. Fall back to the original string in that
case, matching the Python runtime's `int()`/`float()` try/except behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@boring-cyborg

boring-cyborg Bot commented Jun 19, 2026

Copy link
Copy Markdown

Thanks a lot for your first contribution! Please check out our contributing guidelines and don't hesitate to ask whatever you need.
In the meantime, check out the #typescript channel on our Powertools for AWS Lambda Discord: Invite link

@sonarqubecloud

Copy link
Copy Markdown

@kimnamu

kimnamu commented Jun 19, 2026

Copy link
Copy Markdown
Author

Thanks for the automated checks 🙏 A quick note on the Related Issue Check: the PR is correctly linked to #5362 (closes #5362, and it shows under the PR's linked issues), but the check appears to require the linked issue to be triaged/labeled by a maintainer first. As an external contributor I don't have label permissions, so I've left #5362 for maintainer triage.

I opened #5362 specifically because the original parity issue (#3988) is already closed/released, so I couldn't link to it directly — #5362 captures this remaining TypeScript-side gap. Happy to adjust the linkage if you'd prefer a different issue reference. The change itself is a small, test-covered cross-runtime parity fix (matches the Python try/except string fallback).

@dreamorosi dreamorosi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR and for following the correct process & addressing CI checks.

@kimnamu

kimnamu commented Jun 20, 2026

Copy link
Copy Markdown
Author

Thanks for the nudge from the automation 🙏 I tracked down why the Related Issue Check kept failing even though closes #5362 is present and shows under the PR's linked issues.

The body also contained a bare #3988 reference inside the code-comment illustration. The automation scans the body for every #<number> token and expects each to be a linked issue — so the (already-closed) #3988 was being counted as a second, unlinked reference, which tripped the check.

I've rewritten that line so it no longer uses a bare #<number> token; the only remaining issue reference is the real closing link closes #5362. No code changes — body only.

This follow-up was prepared with the help of an AI agent (Claude Code); a human reviewed it before posting.

@kimnamu

kimnamu commented Jun 21, 2026

Copy link
Copy Markdown
Author

The Related Issue Check is green now ✅ — the earlier failure was a stale run that didn't re-evaluate after I cleaned up the issue reference. The PR body now links exactly one issue (Closes #5362), and the check passes on the latest commit.

This is approved and the merge state is clean — ready whenever you'd like to land it. Thanks again for the review!

(This note was prepared with the help of an AI agent (Claude Code); I verified the check status and merge state before posting.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M PR between 30-99 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Bedrock Agent number/integer params lose their value when not numeric (no string fallback like Python)

2 participants