Skip to content

Bug: validate-state-machine-definition produces non-deterministic results for identical input #13171

@YukiMichishita

Description

@YukiMichishita

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Prepare a valid StepFunctions definition: valid.json and an invalid StepFunctions definition: invalid.json.
After starting localstack, immediately call validate-state-machine-definition with valid.json. The validation will return OK. Then, when you provide invalid.json, it will return an error. This part works as expected. However, if you then provide valid.json again, it will return an error.

Expected Behavior

For identical input definitions, validate-state-machine-definition should consistently return the same result. The validation outcome must not depend on call history or internal state

How are you starting LocalStack?

With a docker run command

Steps To Reproduce

How are you starting localstack (e.g., bin/localstack command, arguments, or docker-compose.yml)

docker run localstack/localstack

Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

valid.json

{
  "Comment": "valid definition",
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "Pass",
        "States": {
          "Pass": {
            "QueryLanguage": "JSONPath",
            "Type": "Pass",
            "End": true
          }
        }
      },
      "End": true
    }
  }
}

invalid.json

{
  "Comment": "A description of my state machine",
  "StartAt": "Pass",
  "States": {
    "Pass": {
      "Type": "Pass",
      "End": true,
      "QueryLanguage": "JSONPath"
    }
  },
  "QueryLanguage": "JSONata"
}
$aws stepfunctions validate-state-machine-definition --definition file:///tmp/valid.json
{
    "result": "OK",
    "diagnostics": [],
    "truncated": false
}

$aws stepfunctions validate-state-machine-definition --definition file:///tmp/invalid.json
{
    "result": "FAIL",
    "diagnostics": [
        {
            "severity": "ERROR",
            "code": "SCHEMA_VALIDATION_FAILED",
            "message": "Error=ValueError Args=['Cannot downgrade from JSONata context to a JSONPath context at: [325 313 250 238 232]'] in definition '{\n  \"Comment\": \"A description of my state machine\",\n  \"StartAt\": \"Pass\",\n  \"States\": {\n    \"Pass\": {\n      \"Type\": \"Pass\",\n      \"End\": true,\n      \"QueryLanguage\": \"JSONPath\"\n    }\n  },\n  \"QueryLanguage\": \"JSONata\"\n}\n'."
        }
    ],
    "truncated": false
}

$aws stepfunctions validate-state-machine-definition --definition file:///tmp/valid.json
{
    "result": "FAIL",
    "diagnostics": [
        {
            "severity": "ERROR",
            "code": "SCHEMA_VALIDATION_FAILED",
            "message": "Error=ValueError Args=['Cannot downgrade from JSONata context to a JSONPath context at: [325 313 793 783 288 330 325 313 250 238 232]'] in definition '{\n  \"Comment\": \"valid definition\",\n  \"StartAt\": \"Map\",\n  \"States\": {\n    \"Map\": {\n      \"Type\": \"Map\",\n      \"ItemProcessor\": {\n        \"ProcessorConfig\": {\n          \"Mode\": \"INLINE\"\n        },\n        \"StartAt\": \"Pass\",\n        \"States\": {\n          \"Pass\": {\n            \"QueryLanguage\": \"JSONPath\",\n            \"Type\": \"Pass\",\n            \"End\": true\n          }\n        }\n      },\n      \"End\": true\n    }\n  }\n}\n'."
        }
    ],
    "truncated": false
}

Environment

- OS: macOS Sequoia 15.5
- LocalStack:
  LocalStack version:4.8.2.dev1
  LocalStack Docker image sha:
  LocalStack build date:2025-09-17
  LocalStack build git hash:ad5b3695a

Anything else?

This is likely due to _query_language_per_scope being a class variable within the Processor class. This causes the state of _query_language_per_scope to persist across requests. While it appears intended that the _query_language_per_scope entered during the previous call would be removed by the pop method, I suspect that when an error occurs, the pop operation may not complete all the way.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions