{"record":{"id":"1f9b7cbd9c256d01","repo":"chenhg5/cc-connect","slug":"config-at-least-one-projects-entry-is-require","errorCode":null,"errorMessage":"config: at least one [[projects]] entry is required","messagePattern":"config: at least one \\[\\[projects\\]\\] entry is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"config/config.go","lineNumber":1024,"sourceCode":"func (c *Config) validateInternal(permissive bool) error {\n\tif err := validateDisplayConfig(\"display\", &c.Display); err != nil {\n\t\treturn err\n\t}\n\tswitch strings.ToLower(strings.TrimSpace(c.AttachmentSend)) {\n\tcase \"\", \"on\", \"off\":\n\tdefault:\n\t\treturn fmt.Errorf(\"config: attachment_send must be \\\"on\\\" or \\\"off\\\"\")\n\t}\n\tif c.Relay.TimeoutSecs != nil && *c.Relay.TimeoutSecs < 0 {\n\t\treturn fmt.Errorf(\"config: relay.timeout_secs must be >= 0\")\n\t}\n\tswitch strings.ToLower(strings.TrimSpace(c.Relay.Visibility)) {\n\tcase \"\", \"full\", \"summary\", \"none\":\n\tdefault:\n\t\treturn fmt.Errorf(\"config: relay.visibility must be \\\"full\\\", \\\"summary\\\", or \\\"none\\\"\")\n\t}\n\tif len(c.Projects) == 0 {\n\t\treturn fmt.Errorf(\"config: at least one [[projects]] entry is required\")\n\t}\n\tfor i, proj := range c.Projects {\n\t\tprefix := fmt.Sprintf(\"projects[%d]\", i)\n\t\tif proj.Name == \"\" {\n\t\t\treturn fmt.Errorf(\"config: %s.name is required\", prefix)\n\t\t}\n\t\tif proj.Agent.Type == \"\" {\n\t\t\treturn fmt.Errorf(\"config: %s.agent.type is required\", prefix)\n\t\t}\n\t\tif len(proj.Platforms) == 0 && !permissive {\n\t\t\treturn fmt.Errorf(\"config: %s needs at least one [[projects.platforms]]\", prefix)\n\t\t}\n\t\tfor j, p := range proj.Platforms {\n\t\t\tif p.Type == \"\" {\n\t\t\t\treturn fmt.Errorf(\"config: %s.platforms[%d].type is required\", prefix, j)\n\t\t\t}\n\t\t}\n\t\tif proj.Mode == \"multi-workspace\" {","sourceCodeStart":1006,"sourceCodeEnd":1042,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/config/config.go#L1006-L1042","documentation":"The validator requires at least one [[projects]] entry in the config file. CC-Connect routes messages from platforms to coding agents per project, so an empty or missing projects list leaves the daemon with nothing to run and is rejected at load time in config/config.go.","triggerScenarios":"Loading a config.toml that has no [[projects]] array at all, or where all [[projects]] blocks were commented out or deleted, so c.Projects has length 0.","commonSituations":"Fresh installs with a minimal config containing only [relay] and platform settings; users commenting out their only project while debugging; copying a platform-only snippet from docs.","solutions":["Add at least one [[projects]] block with a name, agent.type, and platforms to config.toml","Un-comment the example [[projects]] section in your config","Copy a working example from config.example.toml"],"exampleFix":"// before\n[relay]\nvisibility = \"summary\"\n// after\n[relay]\nvisibility = \"summary\"\n\n[[projects]]\nname = \"my-app\"\nagent.type = \"claudecode\"\n[[projects.platforms]]\ntype = \"feishu\"","handlingStrategy":"validation","validationCode":"if len(cfg.Projects) == 0 {\n    return fmt.Errorf(\"config.toml has no [[projects]] entries\")\n}","typeGuard":null,"tryCatchPattern":"if err := config.Load(path); err != nil {\n    slog.Error(\"config load failed\", \"err\", err)\n    os.Exit(1)\n}","preventionTips":["Start from config.example.toml and fill in a project block first","Keep at least one [[projects]] block, even a disabled-looking minimal one","Validate config in CI before shipping"],"tags":["config","validation","go"],"backgroundTag":"missing-required-config-field","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"}