larksuite/cli · error
invalid JSON in %s: %w
Error message
invalid JSON in %s: %w
What it means
ReadOpenClawConfig reads an openclaw.json file and unmarshals it into the OpenClawRoot struct (channels + secrets subtree). This error is thrown when the file exists and is readable but its bytes are not valid JSON (json.Unmarshal fails). The path is embedded in the message and the underlying json.SyntaxError/json.UnmarshalTypeError is wrapped via %w, so callers can inspect the cause for offset/type details.
Source
Thrown at internal/binding/reader.go:22
package binding
import (
"encoding/json"
"fmt"
"github.com/larksuite/cli/internal/vfs"
)
// ReadOpenClawConfig reads and parses an openclaw.json file at the given path.
func ReadOpenClawConfig(path string) (*OpenClawRoot, error) {
data, err := vfs.ReadFile(path)
if err != nil {
return nil, err // caller (bind.go) formats user-facing message with path context
}
var root OpenClawRoot
if err := json.Unmarshal(data, &root); err != nil {
return nil, fmt.Errorf("invalid JSON in %s: %w", path, err)
}
return &root, nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Open the file named in the error and run it through a JSON linter (python3 -m json.tool <path>) to find the exact syntax error at the wrapped offset.
- Remove JSON-illegal constructs: comments, trailing commas, single quotes, smart quotes; encoding/json is strict.
- If a placeholder like {{...}} remains unsubstituted, supply the real value or an env template "${VAR}" instead.
- Delete the corrupt file and re-run the tool that generates openclaw.json, or restore it from backup/version control.
- Unwrap the cause in code (errors.As to *json.SyntaxError) to programmatically report line/column offsets.
Example fix
// before (invalid: trailing comma)
{ "channels": { "feishu": { "appId": "cli_x", "appSecret": "s" ,} } }
// after
{ "channels": { "feishu": { "appId": "cli_x", "appSecret": "s" } } } Defensive patterns
Strategy: validation
Validate before calling
func validateOpenClawJSON(path string) error {
data, err := os.ReadFile(path)
if err != nil { return err }
var v any
if err := json.Unmarshal(data, &v); err != nil {
var se *json.SyntaxError
if errors.As(err, &se) {
line := 1 + bytes.Count(data[:se.Offset], []byte("\n"))
return fmt.Errorf("%s: invalid JSON at line %d: %v", path, line, se)
}
return fmt.Errorf("%s: invalid JSON: %w", path, err)
}
return nil
} Type guard
func isOpenClawJSONValid(path string) bool {
data, err := os.ReadFile(path)
if err != nil { return false }
var v any
return json.Unmarshal(data, &v) == nil
} Try / catch
root, err := binding.ReadOpenClawConfig(path)
if err != nil {
var se *json.SyntaxError
if errors.As(err, &se) {
fmt.Fprintf(os.Stderr, "fix JSON syntax at offset %d in %s: %v\n", se.Offset, path, se)
}
return err
} Prevention
- Run python3 -m json.tool openclaw.json (or a JSON linter in CI) after every hand edit or template render.
- Never put comments or trailing commas in openclaw.json; encoding/json is strict.
- Validate generated configs in CI immediately after template substitution.
- Keep openclaw.json in version control so a corrupt edit is easy to revert.
When it happens
Trigger: Calling ReadOpenClawConfig(path) where the file at path contains malformed JSON: truncated file, trailing commas, comments, single quotes, BOM, smart quotes from copy-paste, or an appSecret given as a non-string/non-object literal (the SecretInput.UnmarshalJSON error also surfaces here as an UnmarshalTypeError-style failure).
Common situations: A text editor or heredoc script wrote a partial/corrupt openclaw.json; a template placeholder like {{SECRET}} was never substituted; the file was hand-edited with comments or trailing commas that strict encoding/json rejects; a file-sync tool wrote a zero-byte or half-written file.
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
- invalid JSON in %s: %w
- malformed config
- failed to parse response: %w
- SecretRef.source must be env|file|exec, got %q
- SecretRef.id must be non-empty
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/07d99543141a2e6f.
Report an issue: GitHub.