{"record":{"id":"1ddf89a6cf7ca5bf","repo":"chenhg5/cc-connect","slug":"app-id-and-app-secret-are-required","errorCode":null,"errorMessage":"app_id and app_secret are required","messagePattern":"app_id and app_secret are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/config.go","lineNumber":2030,"sourceCode":"\t\tPlatformAbsIndex: len(cfg.Projects[len(cfg.Projects)-1].Platforms) - 1,\n\t\tPlatformType:     platformType,\n\t}, nil\n}\n\n// SaveFeishuPlatformCredentials updates app_id/app_secret for a project's\n// Feishu/Lark platform and persists the config atomically.\nfunc SaveFeishuPlatformCredentials(opts FeishuCredentialUpdateOptions) (*FeishuCredentialUpdateResult, error) {\n\tconfigMu.Lock()\n\tdefer configMu.Unlock()\n\n\tif ConfigPath == \"\" {\n\t\treturn nil, fmt.Errorf(\"config path not set\")\n\t}\n\tif strings.TrimSpace(opts.ProjectName) == \"\" {\n\t\treturn nil, fmt.Errorf(\"project name is required\")\n\t}\n\tif strings.TrimSpace(opts.AppID) == \"\" || strings.TrimSpace(opts.AppSecret) == \"\" {\n\t\treturn nil, fmt.Errorf(\"app_id and app_secret are required\")\n\t}\n\tif opts.PlatformIndex < 0 {\n\t\treturn nil, fmt.Errorf(\"platform index must be >= 0\")\n\t}\n\tif opts.PlatformType != \"\" && opts.PlatformType != \"feishu\" && opts.PlatformType != \"lark\" {\n\t\treturn nil, fmt.Errorf(\"invalid platform type %q (want feishu or lark)\", opts.PlatformType)\n\t}\n\n\tdata, err := os.ReadFile(ConfigPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read config: %w\", err)\n\t}\n\traw := string(data)\n\tcfg := &Config{}\n\tif err := toml.Unmarshal(data, cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse config: %w\", err)\n\t}\n","sourceCodeStart":2012,"sourceCodeEnd":2048,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/config/config.go#L2012-L2048","documentation":"Feishu platform credentials consist of an App ID and an App Secret; both must be non-empty after trimming. The function refuses to write a partial credential pair, which would leave the platform entry unusable against the Feishu/Lark API.","triggerScenarios":"Calling config.SaveFeishuPlatformCredentials with opts.AppID empty, opts.AppSecret empty, or both (e.g. unset fields, whitespace-only strings, or an incomplete credential collection flow).","commonSituations":"The user only pasted one of the two values from the Feishu open-platform console; a chat-command parser split the input incorrectly; a secret was lost due to shell quoting or env-var expansion problems.","solutions":["Provide both opts.AppID and opts.AppSecret from the Feishu/Lark app credentials page.","Trim whitespace and reject empty values at the caller before calling the function.","Check quoting/escaping when passing the secret via shell or chat message (quotes, env expansion)."],"exampleFix":"// before\nopts := config.FeishuCredentialUpdateOptions{ProjectName: \"p\", AppID: \"cli_a1b2\"} // secret missing\n\n// after\nopts := config.FeishuCredentialUpdateOptions{ProjectName: \"p\", AppID: \"cli_a1b2\", AppSecret: \"xxxx\"}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(appID) == \"\" || strings.TrimSpace(appSecret) == \"\" {\n    return fmt.Errorf(\"both app_id and app_secret are required\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Collect AppID and AppSecret together in one interactive flow so neither is skipped.","Trim inputs and re-prompt when either value is empty.","Watch for shell quoting issues that silently truncate secrets; verify lengths after parsing."],"tags":["config","go","validation","credentials"],"backgroundTag":"missing-credentials","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}