{"record":{"id":"109af947ae24dcfd","repo":"chenhg5/cc-connect","slug":"qqbot-app-secret-is-required","errorCode":null,"errorMessage":"qqbot: app_secret is required","messagePattern":"qqbot: app_secret is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"platform/qqbot/qqbot.go","lineNumber":156,"sourceCode":"// msgTypeQuote indicates a quote (reply) message in the QQ Bot API.\nconst msgTypeQuote = 103\n\n// msgElement represents a message element in QQ Bot event.\n// For quote messages (message_type=103), msg_elements[0] contains the quoted content.\ntype msgElement struct {\n\tContent     string       `json:\"content\"`\n\tAttachments []attachment `json:\"attachments\"`\n}\n\n// New creates a new QQ Bot platform from config options.\nfunc New(opts map[string]any) (core.Platform, error) {\n\tappID, _ := opts[\"app_id\"].(string)\n\tif appID == \"\" {\n\t\treturn nil, fmt.Errorf(\"qqbot: app_id is required\")\n\t}\n\tappSecret, _ := opts[\"app_secret\"].(string)\n\tif appSecret == \"\" {\n\t\treturn nil, fmt.Errorf(\"qqbot: app_secret is required\")\n\t}\n\n\tsandbox, _ := opts[\"sandbox\"].(bool)\n\tallowFrom, _ := opts[\"allow_from\"].(string)\n\tshareSessionInChannel, _ := opts[\"share_session_in_channel\"].(bool)\n\tmarkdownSupport, _ := opts[\"markdown_support\"].(bool)\n\n\tintents := defaultIntents\n\tif v, ok := opts[\"intents\"].(int); ok && v > 0 {\n\t\tintents = v\n\t} else if v, ok := opts[\"intents\"].(float64); ok && v > 0 {\n\t\tintents = int(v)\n\t}\n\n\tcore.CheckAllowFrom(\"qqbot\", allowFrom)\n\tdataDir, _ := opts[\"cc_data_dir\"].(string)\n\treturn &Platform{\n\t\tappID:                 appID,","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L138-L174","documentation":"New() validates required credentials from the opts map before constructing the Platform. It type-asserts opts[\"app_id\"] and opts[\"app_secret\"] to string and returns this error when the app_secret key is absent, not a string, or an empty string. The QQ Bot API requires an app secret to exchange for access tokens, so construction without it is refused immediately.","triggerScenarios":"Calling qqbot.New(opts) where opts[\"app_secret\"] is missing, is nil, or where its concrete type is not string (e.g. it was passed as []byte, a typed constant, or loaded from YAML/JSON as another type).","commonSituations":"Typo in the TOML/YAML key (appsecret, app-secret) so it never reaches opts; secret left out of an environment-driven config loader; secret declared as []byte from os.ReadFile; copying a Feishu/Telegram config block that has no app_secret field.","solutions":["Set app_secret in the platform options as a plain string: opts[\"app_secret\"] = \"your-secret\" in the config.toml [platforms.qqbot] section (or equivalent).","Check the key spelling and casing — it must be exactly \"app_secret\".","Ensure the value is a Go string, not []byte or another type; convert with string(b) if read from a file.","Verify app_id is also set — New checks app_id first, so a missing app_id error can mask a missing secret until app_id is fixed."],"exampleFix":"// before\nopts := map[string]any{\"app_id\": \"123\"}\np, err := qqbot.New(opts) // qqbot: app_secret is required\n// after\nopts := map[string]any{\"app_id\": \"123\", \"app_secret\": os.Getenv(\"QQBOT_APP_SECRET\")}\np, err := qqbot.New(opts)","handlingStrategy":"validation","validationCode":"func validateQQBotOpts(opts map[string]any) error {\n    id, _ := opts[\"app_id\"].(string)\n    sec, _ := opts[\"app_secret\"].(string)\n    if id == \"\" { return errors.New(\"qqbot opts: app_id missing or not a string\") }\n    if sec == \"\" { return errors.New(\"qqbot opts: app_secret missing or not a string\") }\n    return nil\n}","typeGuard":"sec, ok := opts[\"app_secret\"].(string); if !ok || sec == \"\" { /* refuse to construct */ }","tryCatchPattern":null,"preventionTips":["Store secrets as plain strings, never []byte, when building the opts map.","Validate the whole platform config at startup, before New(), with a fail-fast check.","Use consistent key naming (snake_case) across all platform config blocks.","Load secrets from env vars with a startup assertion that they are non-empty."],"tags":["qqbot","config","credentials","initialization"],"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"}