{"record":{"id":"415b0cdd72186c42","repo":"chenhg5/cc-connect","slug":"tuitui-app-id-and-app-secret-are-required","errorCode":null,"errorMessage":"tuitui: app_id and app_secret are required","messagePattern":"tuitui: app_id and app_secret are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"platform/tuitui/tuitui.go","lineNumber":109,"sourceCode":"\t_ core.FormattingInstructionProvider = (*Platform)(nil)\n)\n\n// New creates a TuiTui platform from config options.\n//\n//\t[[projects.platforms]]\n//\ttype = \"tuitui\"\n//\t[projects.platforms.options]\n//\tapp_id = \"${TUITUI_APP_ID}\"\n//\tapp_secret = \"${TUITUI_APP_SECRET}\"\n//\tallow_from = \"*\"              # user accounts, comma-separated\n//\tgroup_allow_from = \"123,456\"  # group IDs, team IDs, or channel IDs\n//\tignore_from = \"bot-xxx\"       # bot accounts to ignore when webhook echoes outbound messages\n//\trequire_mention = true        # group chats and channel posts require @bot\nfunc New(opts map[string]any) (core.Platform, error) {\n\tappID, _ := opts[\"app_id\"].(string)\n\tappSecret, _ := opts[\"app_secret\"].(string)\n\tif appID == \"\" || appSecret == \"\" {\n\t\treturn nil, fmt.Errorf(\"tuitui: app_id and app_secret are required\")\n\t}\n\tapiBase, _ := opts[\"api_base\"].(string)\n\tif apiBase == \"\" {\n\t\tapiBase = defaultAPIBase\n\t}\n\twsBase, _ := opts[\"ws_base\"].(string)\n\tif wsBase == \"\" {\n\t\twsBase = defaultWSBase\n\t}\n\tallowFrom, _ := opts[\"allow_from\"].(string)\n\tcore.CheckAllowFrom(\"tuitui\", allowFrom)\n\tgroupAllowFrom, _ := opts[\"group_allow_from\"].(string)\n\tignoreFrom, _ := opts[\"ignore_from\"].(string)\n\tgroupPolicy, _ := opts[\"group_policy\"].(string)\n\tif groupPolicy == \"\" {\n\t\tgroupPolicy = \"allowlist\"\n\t}\n\tgroupPolicy = strings.ToLower(strings.TrimSpace(groupPolicy))","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/tuitui/tuitui.go#L91-L127","documentation":"The TuiTui platform constructor New() requires app_id and app_secret options; one or both are empty. Without these credentials the platform cannot authenticate with the TuiTui API, so construction fails fast at startup rather than at first request.","triggerScenarios":"Config TOML [platform.tuitui] block missing app_id or app_secret keys; keys present but empty strings; values set under the wrong table so opts never contains them; opts map built programmatically without these keys.","commonSituations":"Fresh deployment with a copied example config not fully filled in; secrets injected via env vars not wired into the opts map; typo in key name (e.g. appid); using another platform's config template.","solutions":["Set both app_id and app_secret in the tuitui platform config block.","Verify the keys are in the correct TOML table for the tuitui platform.","If using env-based secrets, ensure they are loaded into the opts map before New() is called.","Check key spelling against config.example.toml."],"exampleFix":"// before\n[platform.tuitui]\napi_base = \"https://api.example.com\"\n// after\n[platform.tuitui]\napp_id = \"your-app-id\"\napp_secret = \"your-app-secret\"\napi_base = \"https://api.example.com\"","handlingStrategy":"validation","validationCode":"cfg := raw[\"platform.tuitui\"].(map[string]any)\nfor _, k := range []string{\"app_id\", \"app_secret\"} {\n    if v, _ := cfg[k].(string); strings.TrimSpace(v) == \"\" {\n        return fmt.Errorf(\"tuitui config missing %s\", k)\n    }\n}","typeGuard":"func tuituiCredsPresent(opts map[string]any) bool {\n    id, _ := opts[\"app_id\"].(string)\n    sec, _ := opts[\"app_secret\"].(string)\n    return strings.TrimSpace(id) != \"\" && strings.TrimSpace(sec) != \"\"\n}","tryCatchPattern":"plat, err := tuitui.New(opts)\nif err != nil && strings.Contains(err.Error(), \"app_id and app_secret are required\") {\n    return fmt.Errorf(\"startup aborted: fill in tuitui app_id/app_secret in config.toml\")\n}","preventionTips":["Fill in both credential keys when copying config.example.toml","Validate the full platform config at boot before creating platforms","Inject secrets via env and assert their presence before building the opts map","Use a config linter/checksum to catch partially copied config blocks"],"tags":["tuitui","configuration","credentials"],"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-14T00:17:10.932Z"}