{"record":{"id":"1876d30bf40dac67","repo":"chenhg5/cc-connect","slug":"wecom-callback-token-and-callback-aes-key-are-req","errorCode":null,"errorMessage":"wecom: callback_token and callback_aes_key are required","messagePattern":"wecom: callback_token and callback_aes_key are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/wecom.go","lineNumber":134,"sourceCode":"}\n\nfunc New(opts map[string]any) (core.Platform, error) {\n\tmode, _ := opts[\"mode\"].(string)\n\tif mode == \"websocket\" {\n\t\treturn newWebSocket(opts)\n\t}\n\n\tcorpID, _ := opts[\"corp_id\"].(string)\n\tcorpSecret, _ := opts[\"corp_secret\"].(string)\n\tagentID, _ := opts[\"agent_id\"].(string)\n\tcallbackToken, _ := opts[\"callback_token\"].(string)\n\tcallbackAESKey, _ := opts[\"callback_aes_key\"].(string)\n\n\tif corpID == \"\" || corpSecret == \"\" || agentID == \"\" {\n\t\treturn nil, fmt.Errorf(\"wecom: corp_id, corp_secret, and agent_id are required\")\n\t}\n\tif callbackToken == \"\" || callbackAESKey == \"\" {\n\t\treturn nil, fmt.Errorf(\"wecom: callback_token and callback_aes_key are required\")\n\t}\n\n\taesKey, err := decodeAESKey(callbackAESKey)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"wecom: invalid callback_aes_key: %w\", err)\n\t}\n\n\tport, _ := opts[\"port\"].(string)\n\tif port == \"\" {\n\t\tport = \"8081\"\n\t}\n\tpath, _ := opts[\"callback_path\"].(string)\n\tif path == \"\" {\n\t\tpath = \"/wecom/callback\"\n\t}\n\tapiBaseURL, _ := opts[\"api_base_url\"].(string)\n\tapiBaseURL = strings.TrimRight(strings.TrimSpace(apiBaseURL), \"/\")\n\tif apiBaseURL == \"\" {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/wecom.go#L116-L152","documentation":"wecom.New() requires callback_token and callback_aes_key in the options map when running in HTTP callback mode. These credentials come from your WeCom (WeChat Work) admin console and are needed to authenticate and decrypt inbound callback messages. If either is missing or has the wrong type (e.g. set to a non-string), the platform refuses to construct and returns this error.","triggerScenarios":"Calling New(opts) with opts lacking \"callback_token\" or \"callback_aes_key\", or with those keys set to nil/other types so the string type assertion yields \"\". Also triggered if they are present but empty strings. Not triggered in websocket mode (mode==\"websocket\" bypasses this check).","commonSituations":"Freshly wired config.toml where the [platform.wecom] section only has corp_id/corp_secret/agent_id; migrating from websocket mode to callback mode without adding the callback secrets; YAML/TOML keys misnamed (callback-token vs callback_token) so the lookup misses; values defined as environment-variable placeholders that resolve to empty.","solutions":["Add callback_token and callback_aes_key (both non-empty strings) from the WeCom app's 'Receive Messages' configuration page to the platform options","Verify the keys in your config use underscores exactly: callback_token, callback_aes_key","Confirm the values are strings in the config file (quoted), not empty or null","If you do not need callback mode, set mode = \"websocket\" in the options instead","Run the TestNew tests with a minimal valid opts map to confirm which field is missing"],"exampleFix":"// before\nopts := map[string]any{\"corp_id\": \"cid\", \"corp_secret\": \"sec\", \"agent_id\": \"1\"}\np, err := wecom.New(opts) // error: callback_token and callback_aes_key are required\n// after\nopts := map[string]any{\n  \"corp_id\": \"cid\", \"corp_secret\": \"sec\", \"agent_id\": \"1\",\n  \"callback_token\": \"myToken\", \"callback_aes_key\": base43EncodingOfAESKey,\n}\np, err := wecom.New(opts)","handlingStrategy":"validation","validationCode":"func validateWecomOpts(opts map[string]any) error {\n\tfor _, k := range []string{\"corp_id\", \"corp_secret\", \"agent_id\", \"callback_token\", \"callback_aes_key\"} {\n\t\tv, _ := opts[k].(string)\n\t\tif v == \"\" {\n\t\t\treturn fmt.Errorf(\"wecom: missing option %q\", k)\n\t\t}\n\t}\n\tif len(opts[\"callback_aes_key\"].(string)) != 43 {\n\t\treturn fmt.Errorf(\"wecom: callback_aes_key should be 43 chars\")\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep a config checklist covering every required wecom key before startup","Quote string values in TOML/YAML so they never collapse to empty","Parse the config and dry-run New() in CI to catch missing fields early","Use websocket mode only deliberately; callback mode always needs both callback secrets"],"tags":["wecom","config","validation","startup"],"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"}