{"record":{"id":"5859ef17f0594212","repo":"larksuite/cli","slug":"malformed-config","errorCode":null,"errorMessage":"malformed config","messagePattern":"malformed config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/core/config.go","lineNumber":220,"sourceCode":"\n// GetConfigDir returns the config directory path for the current workspace.\n// When workspace is local (default), this returns the same path as before\n// (LARKSUITE_CLI_CONFIG_DIR or ~/.lark-cli) — fully backward-compatible.\n// When workspace is openclaw/hermes, returns base/openclaw or base/hermes.\nfunc GetConfigDir() string {\n\treturn GetRuntimeDir()\n}\n\n// GetConfigPath returns the config file path for the current workspace.\nfunc GetConfigPath() string {\n\treturn filepath.Join(GetConfigDir(), \"config.json\")\n}\n\n// ErrMalformedConfig marks a config-load failure caused by malformed file\n// content (unparseable JSON, structurally empty) rather than a missing or\n// unreadable file. Callers classify with errors.Is rather than sniffing the\n// message text.\nvar ErrMalformedConfig = errors.New(\"malformed config\")\n\n// LoadMultiAppConfig loads multi-app config from disk.\nfunc LoadMultiAppConfig() (*MultiAppConfig, error) {\n\tdata, err := vfs.ReadFile(GetConfigPath())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar multi MultiAppConfig\n\tif err := json.Unmarshal(data, &multi); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid config format: %w: %w\", ErrMalformedConfig, err)\n\t}\n\tif len(multi.Apps) == 0 {\n\t\treturn nil, fmt.Errorf(\"invalid config format: no apps: %w\", ErrMalformedConfig)\n\t}\n\treturn &multi, nil\n}\n","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/core/config.go#L202-L238","documentation":"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).","triggerScenarios":"Calling LoadMultiAppConfig when the config file contains invalid JSON ('invalid config format' wrap) or parses but has len(Apps)==0 ('no apps' wrap).","commonSituations":"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.","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"],"exampleFix":"// before (config.json)\n{ \"apps\": [ { \"appId\": \"cli_x\",\n// after\n{ \"apps\": [ { \"appId\": \"cli_x\", \"appSecret\": \"...\" } ] }","handlingStrategy":"type-guard","validationCode":"data, err := os.ReadFile(cfgPath)\nvar multi core.MultiAppConfig\nif err := json.Unmarshal(data, &multi); err != nil || len(multi.Apps) == 0 {\n    // config is malformed — run `lark-cli config init`\n}","typeGuard":"func isMalformedConfig(err error) bool { return errors.Is(err, core.ErrMalformedConfig) }","tryCatchPattern":"cfg, err := core.LoadMultiAppConfig()\nif errors.Is(err, core.ErrMalformedConfig) {\n    // distinguish from missing/unreadable file: prompt re-init\n}","preventionTips":["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"],"tags":["config","json","validation"],"backgroundTag":"malformed-config-file","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}