Skip to content

update_simulation always adds api_version, making empty-PATCH guard unreachable #3449

@MaxGhenis

Description

@MaxGhenis

Summary

SimulationService.update_simulation always appends api_version = ? to update_fields, so the "no fields supplied" guard in both the service and the route handler is unreachable. A PATCH with an empty body (or a body with only unknown keys) silently rewrites api_version with no other user intent.

Location

  • Service: policyengine_api/services/simulation_service.py:478-500
  • Route: policyengine_api/routes/simulation_routes.py:191-192

What goes wrong

Service (excerpt):

update_fields = []
update_values = []

if status is not None:
    update_fields.append("status = ?")
    update_values.append(status)

if output is not None:
    update_fields.append("output = ?")
    update_values.append(output)

if error_message is not None:
    update_fields.append("error_message = ?")
    update_values.append(error_message)

update_fields.append("api_version = ?")
update_values.append(api_version)

if not update_fields:        # always False — api_version was just appended
    print("No fields to update")
    return False

Route (excerpt):

if not success:
    raise BadRequest("No fields to update")

The route handler's BadRequest("No fields to update") can therefore never fire. A client PATCH with {} still runs UPDATE simulation SET api_version = ? WHERE ..., which (a) mutates a row the client didn't ask to mutate and (b) masks the bad input.

Suggested fix

Only stamp api_version when there is at least one real user-supplied field, and validate earlier:

if status is None and output is None and error_message is None:
    return False

# ... build update_fields for real inputs ...
update_fields.append("api_version = ?")
update_values.append(api_version)

Or reject empty payloads in the route before calling the service.

Severity

Medium.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions