ERROR 3141 (42000): In this situation, path expressions may not contain the * and ** tokens. is raised when a JSON path expression containing wildcard tokens (* or **) is used in a context where wildcards are not permitted. The error symbol is ER_INVALID_JSON_PATH_WILDCARD.
Impact
This error causes the statement to fail immediately and return no results. Any query that uses a JSON path with wildcards in a write-path function — such as JSON_SET, JSON_INSERT, JSON_REPLACE, or JSON_REMOVE — will be rejected. Because these functions modify specific values at a known location, wildcards are inherently ambiguous and MySQL refuses them rather than guessing which path to update.
Developers commonly encounter this when constructing JSON paths dynamically from user input or configuration, where a wildcard character ends up in the path string, or when porting expressions from JSON_EXTRACT (which does support wildcards) to one of the mutating functions (which do not).
Common Causes
Using
*or**in a mutating JSON function. Functions likeJSON_SET,JSON_INSERT,JSON_REPLACE, andJSON_REMOVErequire an unambiguous path pointing to a single location. A path like$.tags[*]or$**.nameis rejected because MySQL cannot determine which element to modify.Copying a read path expression into a write context. A path such as
$[*]is perfectly valid inJSON_EXTRACTto retrieve all array elements, but passing the same expression toJSON_SETtriggers error 3141.Dynamically generated paths that accidentally include wildcards. Application code that assembles path strings from user-supplied keys or templating logic may inadvertently produce a path containing
*.Typos or escaping issues in path literals. A path like
$.items.*intended to reach a specific key but containing a trailing.*wildcard will be rejected. Similarly, a double-asterisk**used for recursive descent is only allowed in read functions.
Troubleshooting and Resolution Steps
Identify the offending path expression. Run the statement in the MySQL shell or check the application logs to see the exact path string being passed:
-- Example that triggers error 3141 UPDATE products SET metadata = JSON_SET(metadata, '$.tags[*]', 'sale') WHERE id = 1; -- ERROR 3141 (42000): In this situation, path expressions may not contain the * and ** tokens.Replace wildcards with a specific path for write operations. If you need to update a known element, use a concrete index or key:
-- Update a specific array element by index UPDATE products SET metadata = JSON_SET(metadata, '$.tags[0]', 'sale') WHERE id = 1;Use
JSON_EXTRACT(which supports wildcards) for reads, not writes. If your goal is to read all matching values,JSON_EXTRACTaccepts wildcard paths:-- Valid: wildcards are allowed in JSON_EXTRACT SELECT JSON_EXTRACT(metadata, '$.tags[*]') FROM products WHERE id = 1;To update every element of a JSON array, iterate in application code or use a generated column approach. MySQL has no single-statement way to apply a wildcard update across all array elements. A common pattern is to read the value, modify it in application code, and write it back:
-- Step 1: read the array SELECT JSON_EXTRACT(metadata, '$.tags') FROM products WHERE id = 1; -- Step 2: rebuild the array in your application, then write it back UPDATE products SET metadata = JSON_SET(metadata, '$.tags', CAST('["sale","new"]' AS JSON)) WHERE id = 1;Validate dynamically constructed paths before executing. In application code, assert that a path string contains no
*characters before passing it to a mutating JSON function:# Python example def safe_json_path(path: str) -> str: if '*' in path: raise ValueError(f"Wildcard not allowed in write path: {path}") return pathCheck all JSON-mutating calls in stored procedures and triggers. Use
SHOW CREATE PROCEDUREor inspectinformation_schema.ROUTINESto find any routine that builds paths dynamically:SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE ROUTINE_DEFINITION LIKE '%JSON_SET%' OR ROUTINE_DEFINITION LIKE '%JSON_REPLACE%' OR ROUTINE_DEFINITION LIKE '%JSON_REMOVE%';
Additional Information
- The SQLSTATE
42000indicates a syntax error or access rule violation — the same class used for general SQL syntax errors. - Related error 3143 (
ER_INVALID_JSON_PATH_ARRAY_CELL) is raised when a path expression used in a write context does not resolve to a single cell. - Related error 3140 (
ER_INVALID_JSON_TEXT) is raised when the JSON document itself is malformed, as opposed to the path expression. - The wildcard restriction applies to all versions of MySQL that include JSON support (5.7.8 and later). The error code 3141 and its message have remained stable across MySQL 5.7, 8.0, and 8.4.
- MariaDB has a compatible JSON function set but may surface similar restrictions with different error codes.
- ORMs such as SQLAlchemy, TypeORM, and Hibernate that generate
JSON_SETcalls from update expressions must ensure any user-supplied key names are sanitized before being embedded in a path string.
Frequently Asked Questions
Why does JSON_EXTRACT accept * but JSON_SET does not?
JSON_EXTRACT is a read-only function and can return multiple values as a JSON array when a wildcard matches several elements. JSON_SET must write to a specific location; a wildcard match could resolve to zero, one, or many paths, making the semantics undefined. MySQL enforces this distinction at parse time and returns error 3141 rather than silently ignoring extra matches.
Can I update all elements of a JSON array in one SQL statement without wildcards?
Not directly with JSON_SET. A common workaround is to overwrite the entire array value using JSON_SET with a path pointing to the array key itself (e.g., $.tags), passing the new fully-built array as the value. Another approach is to use a stored procedure that loops over JSON_LENGTH iterations and updates each index individually.
I see the path in my code looks correct — could the * be coming from somewhere else?
Yes. Check string interpolation in your ORM or query builder: a key name fetched from a configuration file, environment variable, or database column could contain a literal asterisk. Log or print the final path string before it reaches MySQL to confirm exactly what is being sent.
Does this error appear in JSON_SEARCH?
No. JSON_SEARCH is a read function that returns the path of a matching value; it does not mutate the document and therefore permits wildcards in the path argument without raising error 3141.