larksuite/cli · error
malformed config
Error message
malformed config
What it means
ErrMalformedConfig marks a config-load failure caused by bad file content — unparseable JSON or a structurally empty apps list — as opposed to a missing or unreadable file. LoadMultiAppConfig wraps JSON unmarshal failures and the zero-apps case with this sentinel so callers classify with errors.Is instead of sniffing message text (see isMalformedConfigError).
Source
Thrown at internal/core/config.go:220
// GetConfigDir returns the config directory path for the current workspace.
// When workspace is local (default), this returns the same path as before
// (LARKSUITE_CLI_CONFIG_DIR or ~/.lark-cli) — fully backward-compatible.
// When workspace is openclaw/hermes, returns base/openclaw or base/hermes.
func GetConfigDir() string {
return GetRuntimeDir()
}
// GetConfigPath returns the config file path for the current workspace.
func GetConfigPath() string {
return filepath.Join(GetConfigDir(), "config.json")
}
// ErrMalformedConfig marks a config-load failure caused by malformed file
// content (unparseable JSON, structurally empty) rather than a missing or
// unreadable file. Callers classify with errors.Is rather than sniffing the
// message text.
var ErrMalformedConfig = errors.New("malformed config")
// LoadMultiAppConfig loads multi-app config from disk.
func LoadMultiAppConfig() (*MultiAppConfig, error) {
data, err := vfs.ReadFile(GetConfigPath())
if err != nil {
return nil, err
}
var multi MultiAppConfig
if err := json.Unmarshal(data, &multi); err != nil {
return nil, fmt.Errorf("invalid config format: %w: %w", ErrMalformedConfig, err)
}
if len(multi.Apps) == 0 {
return nil, fmt.Errorf("invalid config format: no apps: %w", ErrMalformedConfig)
}
return &multi, nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Fix the JSON syntax in the config file (validate with a JSON linter)
- Re-run `lark-cli config init` to regenerate a valid config with at least one app
- Back up and recreate the config if the corruption is unclear
Example fix
// before (config.json)
{ "apps": [ { "appId": "cli_x",
// after
{ "apps": [ { "appId": "cli_x", "appSecret": "..." } ] } Defensive patterns
Strategy: type-guard
Validate before calling
data, err := os.ReadFile(cfgPath)
var multi core.MultiAppConfig
if err := json.Unmarshal(data, &multi); err != nil || len(multi.Apps) == 0 {
// config is malformed — run `lark-cli config init`
} Type guard
func isMalformedConfig(err error) bool { return errors.Is(err, core.ErrMalformedConfig) } Try / catch
cfg, err := core.LoadMultiAppConfig()
if errors.Is(err, core.ErrMalformedConfig) {
// distinguish from missing/unreadable file: prompt re-init
} Prevention
- Validate config JSON after any manual edit
- Avoid editing the config with tools that may truncate writes
- Run `lark-cli config init` to regenerate instead of hand-crafting
- Keep a backup of a known-good config
When it happens
Trigger: Calling LoadMultiAppConfig when the config file contains invalid JSON ('invalid config format' wrap) or parses but has len(Apps)==0 ('no apps' wrap).
Common situations: User hand-edited the config file and broke the JSON; an editor or script truncated it; running `config init` output was redirected incorrectly leaving an empty or apps-less 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
- SecretRef.source must be env|file|exec, got %q
- SecretRef.id must be non-empty
- appSecret must be a string or {source, provider?, id} object
- appSecret must be a string or {source, id} object
- Invalid column: {column!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/5859ef17f0594212.
Report an issue: GitHub.