Skip to content

Fix: Fix vector and color parameter validation to accept JSON string inputs#625

Merged
Scriptwonder merged 3 commits into
CoplayDev:betafrom
whatevertogo:fix/gameobject-scale-validation
Jan 27, 2026
Merged

Fix: Fix vector and color parameter validation to accept JSON string inputs#625
Scriptwonder merged 3 commits into
CoplayDev:betafrom
whatevertogo:fix/gameobject-scale-validation

Conversation

@whatevertogo

@whatevertogo whatevertogo commented Jan 25, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes Pydantic validation error when clients pass vector/color parameters as JSON strings (e.g., "[2, 2, 2]").

Previously, parameters like scale, position, rotation, and color were typed as list[float], causing string inputs to be rejected at the Pydantic validation stage before reaching the normalization logic.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Changes Made

  • manage_gameobject.py:

    • Changed parameter types from list[float] to list[float] | str for position, rotation, scale, and offset
    • Modified _normalize_vector() to return (value, error_message) tuple instead of silently returning None on invalid input
    • Added detailed error messages for invalid vector values
  • manage_material.py:

    • Changed color parameter type from list[float] to list[float] | str
    • Error handling already existed via _normalize_color()

Testing/Screenshots/Recordings

Test Results

Test Case Input Result
String format scale "[2, 2, 2]" ✅ Success: {x:2, y:2, z:2}
List format [1, 2, 3] ✅ Success
Multi-parameter Mixed string/list ✅ Success
Invalid string "invalid" ✅ Clear error message
Wrong format "[1, 2]" ✅ Clear error message

Error Message Example

Before: Input should be a valid list [type=list_type, input_value='[2, 2, 2]', input_type=str]
After:  scale must be a [x, y, z] array (list or JSON string), got: invalid

Documentation Updates

  • I have added/removed/modified tools or resources
  • If yes, I have updated all documentation files using:
    • The LLM prompt at tools/UPDATE_DOCS_PROMPT.md (recommended)
    • Manual updates following the guide at tools/UPDATE_DOCS.md

Note: Parameter type changes are reflected in the tool schema automatically. No manual documentation update required as the description text already mentions "(list or JSON string)".

Related Issues

Fixes the validation error: Input should be a valid list [type=list_type, input_value='[2, 2, 2]', input_type=str]

Additional Notes

  • The implementation follows existing patterns in the codebase:
    • read_console.py: types: Annotated[list[Literal[...]] | str, ...]
    • run_tests.py: test_names: Annotated[list[str] | str, ...]
  • Error handling pattern matches _normalize_component_properties() which returns (parsed_dict, error_message)
  • Backward compatible: existing list-format inputs continue to work

Summary by Sourcery

Allow vector and color tool parameters to accept JSON strings and improve validation error reporting for game object management.

Bug Fixes:

  • Fix rejection of JSON string inputs for position, rotation, scale, offset, and color parameters by updating their accepted types and normalization logic.
  • Return clear, parameter-specific error messages when vector normalization fails instead of silently falling back or surfacing generic Pydantic list validation errors.

Summary by CodeRabbit

  • Improvements
    • Vector parameters (position, rotation, scale, offset) accept both arrays and JSON/string formats.
    • Color inputs now accept arrays or JSON/string formats.
    • Component property values accept primitive and collection types (strings, numbers, booleans, dicts, lists).
  • Bug Fixes
    • Stronger validation: invalid inputs now return clear error responses immediately instead of proceeding with partial data.

✏️ Tip: You can customize this high-level summary in your review settings.

whatevertogo and others added 2 commits January 26, 2026 07:15
The Pydantic validation in FastMCP occurs before function execution,
causing validation errors when clients pass string values like '[2, 2, 2]'
for parameters typed as `list[float] | str`. Since the code already has
normalization functions (_normalize_vector, _normalize_color) that handle
string inputs, change the type annotations to `Any` to bypass Pydantic's
strict validation.

Affected parameters:
- manage_gameobject: position, rotation, scale, offset
- manage_material: color

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change parameter types from `list[float]` to `list[float] | str` to accept
  both list and JSON string inputs (consistent with read_console/run_tests)
- Modify _normalize_vector to return (value, error_message) tuple instead of
  silently returning None on invalid input
- Add detailed error messages for invalid vector values

This fixes the Pydantic validation error when clients pass string values
like "[2, 2, 2]" for scale/position/rotation parameters.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 25, 2026 23:51
@sourcery-ai

sourcery-ai Bot commented Jan 25, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Allows vector-like and color parameters to be passed as either lists or JSON strings, and centralizes detailed validation/error messaging in the vector normalization helper so manage_gameobject can return clear, user-facing errors instead of raw Pydantic validation failures.

File-Level Changes

Change Details Files
Vector parameters now accept both list and JSON string inputs with explicit normalization errors surfaced to the caller.
  • Updated manage_gameobject tool parameter annotations for position, rotation, scale, and offset to accept list[float] or str and documented this in their descriptions.
  • Refactored _normalize_vector to return a (parsed_vector, error_message) tuple, performing detailed type/shape/value checks for lists, JSON strings, and comma-separated strings.
  • Replaced previous silent fallbacks/defaults by wiring manage_gameobject to call _normalize_vector for each vector parameter and immediately return a structured error response when normalization fails.
Server/src/services/tools/manage_gameobject.py
Color parameter in material management tool can now be passed as JSON string in addition to list input.
  • Relaxed the color parameter type in manage_material to list[float]
str to align with the vector parameter behavior in manage_gameobject.
  • Updated the color parameter description to mention acceptance of list or JSON string while continuing to rely on existing _normalize_color handling.

  • Tips and commands

    Interacting with Sourcery

    • Trigger a new review: Comment @sourcery-ai review on the pull request.
    • Continue discussions: Reply directly to Sourcery's review comments.
    • Generate a GitHub issue from a review comment: Ask Sourcery to create an
      issue from a review comment by replying to it. You can also reply to a
      review comment with @sourcery-ai issue to create an issue from it.
    • Generate a pull request title: Write @sourcery-ai anywhere in the pull
      request title to generate a title at any time. You can also comment
      @sourcery-ai title on the pull request to (re-)generate the title at any time.
    • Generate a pull request summary: Write @sourcery-ai summary anywhere in
      the pull request body to generate a PR summary at any time exactly where you
      want it. You can also comment @sourcery-ai summary on the pull request to
      (re-)generate the summary at any time.
    • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
      request to (re-)generate the reviewer's guide at any time.
    • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
      pull request to resolve all Sourcery comments. Useful if you've already
      addressed all the comments and don't want to see them anymore.
    • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
      request to dismiss all existing Sourcery reviews. Especially useful if you
      want to start fresh with a new review - don't forget to comment
      @sourcery-ai review to trigger a new review!

    Customizing Your Experience

    Access your dashboard to:

    • Enable or disable review features such as the Sourcery-generated pull request
      summary, the reviewer's guide, and others.
    • Change the review language.
    • Add, remove or edit custom review instructions.
    • Adjust other review settings.

    Getting Help

    @coderabbitai

    coderabbitai Bot commented Jan 25, 2026

    Copy link
    Copy Markdown
    Contributor

    Caution

    Review failed

    The pull request is closed.

    📝 Walkthrough

    Walkthrough

    Enhanced error reporting and input flexibility for vector and color parameters across tools. _normalize_vector now returns (value, error_message) and accepts contextual names; manage_gameobject propagates validation errors for position/rotation/scale/offset and component_properties; manage_material accepts color as list or JSON string; manage_components narrows value types in its signature.

    Changes

    Cohort / File(s) Summary
    GameObject vector & properties validation
    Server/src/services/tools/manage_gameobject.py
    Reworked _normalize_vector to return (parsed_vector, error_message) and accept param_name for contextual messages. Position, rotation, scale, offset now accept `list[float]
    Material color input
    Server/src/services/tools/manage_material.py
    Updated color parameter annotation to accept `list[float]
    Component value type tightening
    Server/src/services/tools/manage_components.py
    Updated manage_components value parameter type from Any to `str

    Estimated code review effort

    🎯 3 (Moderate) | ⏱️ ~25 minutes

    Poem

    🐰 I nibbled strings and lists today,

    I sorted numbers, chased errors away,
    Position, scale, and color too,
    Now parse cleanly — hip-hop-hue! 🥕✨

    🚥 Pre-merge checks | ✅ 2 | ❌ 1
    ❌ Failed checks (1 warning)
    Check name Status Explanation Resolution
    Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
    ✅ Passed checks (2 passed)
    Check name Status Explanation
    Description check ✅ Passed The description is comprehensive and well-structured, covering purpose, type of change, specific file changes, testing with examples, and backward compatibility notes.
    Title check ✅ Passed The title 'Fix: Fix vector and color parameter validation to accept JSON string inputs' accurately describes the core changes: enhancing vector and color parameter handling to support JSON string inputs in addition to lists, with improved validation error messages.

    ✏️ Tip: You can configure your own custom pre-merge checks in the settings.

    ✨ Finishing touches
    • 📝 Generate docstrings

    Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

    ❤️ Share

    Comment @coderabbitai help to get the list of available commands and usage tips.

    @sourcery-ai sourcery-ai Bot 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.

    Hey - I've found 1 issue, and left some high level feedback:

    • The _normalize_vector error messages say the value 'must be a list or JSON string' even though tuples and comma-separated strings are also accepted; consider aligning the messages with the actual accepted formats to avoid confusing users.
    • The repeated pattern for normalizing position, rotation, scale, and offset (call _normalize_vector, then immediately return on *_error) could be refactored into a small helper or loop to reduce duplication and make it easier to extend with new vector parameters.
    Prompt for AI Agents
    Please address the comments from this code review:
    
    ## Overall Comments
    - The `_normalize_vector` error messages say the value 'must be a list or JSON string' even though tuples and comma-separated strings are also accepted; consider aligning the messages with the actual accepted formats to avoid confusing users.
    - The repeated pattern for normalizing `position`, `rotation`, `scale`, and `offset` (call `_normalize_vector`, then immediately return on `*_error`) could be refactored into a small helper or loop to reduce duplication and make it easier to extend with new vector parameters.
    
    ## Individual Comments
    
    ### Comment 1
    <location> `Server/src/services/tools/manage_gameobject.py:16-25` </location>
    <code_context>
    
    
    -def _normalize_vector(value: Any, default: Any = None) -> list[float] | None:
    +def _normalize_vector(value: Any, param_name: str = "vector") -> tuple[list[float] | None, str | None]:
         """
         Robustly normalize a vector parameter to [x, y, z] format.
    </code_context>
    
    <issue_to_address>
    **suggestion:** Distinguish list/tuple inputs with incorrect length from entirely invalid types in error messages.
    
    For non-string inputs, any list/tuple with length ≠ 3 falls through to the generic `return None, f"{param_name} must be a list or JSON string, got {type(value).__name__}"`, yielding misleading errors like `position must be a list or JSON string, got list` when the issue is the element count.
    
    Consider handling this explicitly:
    ```python
    if isinstance(value, (list, tuple)):
        if len(value) != 3:
            return None, f"{param_name} must have exactly 3 elements [x, y, z], got {len(value)}: {value}"
        try:
            vec = [float(value[0]), float(value[1]), float(value[2])]
            ...
    ```
    so callers get a precise, actionable message when the length is wrong.
    
    Suggested implementation:
    
    ```python
        # If already a list/tuple, ensure it has exactly 3 elements and convert to floats
        if isinstance(value, (list, tuple)):
            if len(value) != 3:
                return None, f"{param_name} must have exactly 3 elements [x, y, z], got {len(value)}: {value}"
    
    ```
    
    This change assumes that the existing body of the `if` block continues to convert the three elements to floats and handle any conversion errors as before. No further changes are required unless other parts of the function explicitly depend on the earlier `and len(value) == 3` condition, in which case they should be updated to rely on the new early return for incorrect lengths.
    </issue_to_address>

    Sourcery is free for open source - if you like our reviews please consider sharing them ✨
    Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

    Comment on lines +16 to 25
    def _normalize_vector(value: Any, param_name: str = "vector") -> tuple[list[float] | None, str | None]:
    """
    Robustly normalize a vector parameter to [x, y, z] format.
    Handles: list, tuple, JSON string, comma-separated string.
    Returns None if parsing fails.
    Returns (parsed_vector, error_message). If error_message is set, parsed_vector is None.
    """
    if value is None:
    return default
    return None, None

    # If already a list/tuple with 3 elements, convert to floats

    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.

    suggestion: Distinguish list/tuple inputs with incorrect length from entirely invalid types in error messages.

    For non-string inputs, any list/tuple with length ≠ 3 falls through to the generic return None, f"{param_name} must be a list or JSON string, got {type(value).__name__}", yielding misleading errors like position must be a list or JSON string, got list when the issue is the element count.

    Consider handling this explicitly:

    if isinstance(value, (list, tuple)):
        if len(value) != 3:
            return None, f"{param_name} must have exactly 3 elements [x, y, z], got {len(value)}: {value}"
        try:
            vec = [float(value[0]), float(value[1]), float(value[2])]
            ...

    so callers get a precise, actionable message when the length is wrong.

    Suggested implementation:

        # If already a list/tuple, ensure it has exactly 3 elements and convert to floats
        if isinstance(value, (list, tuple)):
            if len(value) != 3:
                return None, f"{param_name} must have exactly 3 elements [x, y, z], got {len(value)}: {value}"

    This change assumes that the existing body of the if block continues to convert the three elements to floats and handle any conversion errors as before. No further changes are required unless other parts of the function explicitly depend on the earlier and len(value) == 3 condition, in which case they should be updated to rely on the new early return for incorrect lengths.

    Copilot AI 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.

    Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

    @whatevertogo whatevertogo changed the title Fix: validation problem Fix: Fix vector and color parameter validation to accept JSON string inputs Jan 26, 2026
    @Scriptwonder

    Copy link
    Copy Markdown
    Collaborator

    Thanks! Looks good to me. I will add some fix of manage_components script in this PR and upload it together later.

    @Scriptwonder Scriptwonder merged commit 4991d71 into CoplayDev:beta Jan 27, 2026
    1 check was pending
    @whatevertogo whatevertogo deleted the fix/gameobject-scale-validation branch February 11, 2026 20:36
    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.

    3 participants