octobercms/october · warning · ValidationException
Invalid JSON: :error
Error message
Invalid JSON: :error
What it means
The backend composer.json editor (Updates > Manage projects) saves through manage_onSaveComposer. It runs json_decode($content, JSON_THROW_ON_ERROR) and converts any JsonException into a ValidationException on the content field with the message 'Invalid JSON: <parser error>'. File::put(base_path('composer.json'), ...) only runs after the content parses cleanly.
Source
Thrown at modules/system/controllers/updates/HasComposerEditor.php:38
$widget->getField('content')->value(File::get($composerFile));
$this->vars['widget'] = $widget;
return $this->makePartial('composer_form');
}
/**
* manage_onSaveComposer validates and saves the composer.json file
*/
public function manage_onSaveComposer()
{
$content = post('Composer')['content'] ?? '';
try {
json_decode($content, flags: JSON_THROW_ON_ERROR);
}
catch (\JsonException $ex) {
throw new ValidationException(['content' => __("Invalid JSON: :error", [
'error' => $ex->getMessage()
])]);
}
File::put(base_path('composer.json'), $content);
Flash::success(__("Composer file updated successfully."));
}
/**
* makeComposerFormWidget creates a form widget for the composer editor
*/
protected function makeComposerFormWidget()
{
$config = $this->makeConfig([
'alias' => 'formComposerEditor',
'arrayName' => 'Composer',
'model' => new \Model,View on GitHub (pinned to b608633a7e)
Solutions
- Fix the syntax error named in the JsonException message (it includes the position)
- Validate before saving: JSON.parse the content client-side, or run it through jsonlint
- For intentionally empty content, save a minimal valid document such as {} instead of blank text
Example fix
// before
{
"require": {
"october/system": "^3.0",
}
}
// after
{
"require": {
"october/system": "^3.0"
}
} Defensive patterns
Strategy: validation
Validate before calling
// server-side, before saving
try { json_decode($content, flags: JSON_THROW_ON_ERROR); } catch (\JsonException $ex) { /* block save, show $ex->getMessage() */ }
// client-side
try { JSON.parse(content); } catch (e) { /* block submit */ } Prevention
- Never allow blank submissions; substitute {} for empty content
- Run JSON.parse in the editor before enabling the save button
- Remember composer.json is strict JSON: no trailing commas, no single quotes, no comments
When it happens
Trigger: Saving composer.json with a trailing comma, single-quoted strings, unquoted keys, smart quotes, an unterminated object, or an empty string (post('Composer')['content'] defaults to '' which also fails json_decode with 'Syntax error').
Common situations: Hand-editing composer.json in the UI and forgetting JSON strictness; pasting YAML-ish config; submitting the form with a cleared textarea.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The property name is not specified.
- Cannot find the requested row group.
- Inspector container ${$containerHolder.data['inspector-conta
- Cannot switch to container: a container element is not found
- Inspector surface unique ID should be defined.
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/ea46c1ef6e8b585c.
Report an issue: GitHub.