{"record":{"id":"368a45541d78f8cc","repo":"chenhg5/cc-connect","slug":"weixin-token-is-required-ilink-bot-bearer-token","errorCode":null,"errorMessage":"weixin: token is required (ilink bot Bearer token)","messagePattern":"weixin: token is required \\(ilink bot Bearer token\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/weixin.go","lineNumber":173,"sourceCode":"\tvar b strings.Builder\n\tfor _, r := range s {\n\t\tswitch r {\n\t\tcase '/', '\\\\', ':', '\\x00':\n\t\t\tb.WriteByte('_')\n\t\tdefault:\n\t\t\tb.WriteRune(r)\n\t\t}\n\t}\n\treturn b.String()\n}\n\n// New constructs a Weixin platform. Required options: token.\n// Optional: base_url, cdn_base_url (default https://novac2c.cdn.weixin.qq.com/c2c), allow_from, route_tag, account_id, long_poll_timeout_ms,\n// state_dir (override persistence dir), proxy, cc_data_dir + cc_project (injected by main).\nfunc New(opts map[string]any) (core.Platform, error) {\n\ttoken, _ := opts[\"token\"].(string)\n\tif strings.TrimSpace(token) == \"\" {\n\t\treturn nil, fmt.Errorf(\"weixin: token is required (ilink bot Bearer token)\")\n\t}\n\tallowFrom, _ := opts[\"allow_from\"].(string)\n\tcore.CheckAllowFrom(\"weixin\", allowFrom)\n\n\tbaseURL, _ := opts[\"base_url\"].(string)\n\tcdnBaseURL, _ := opts[\"cdn_base_url\"].(string)\n\tif strings.TrimSpace(cdnBaseURL) == \"\" {\n\t\tcdnBaseURL = defaultCDNBaseURL\n\t}\n\tcdnBaseURL = strings.TrimRight(strings.TrimSpace(cdnBaseURL), \"/\")\n\trouteTag, _ := opts[\"route_tag\"].(string)\n\taccountLabel, _ := opts[\"account_id\"].(string)\n\tif accountLabel == \"\" {\n\t\taccountLabel = \"default\"\n\t}\n\tlp := pickInt(opts[\"long_poll_timeout_ms\"])\n\n\t// Send-volume quota (see defaultBurstLimit constants). 0 disables the quota.","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/weixin.go#L155-L191","documentation":"New constructs the weixin platform and requires a non-empty \"token\" option — the ilink bot Bearer token used to authenticate against WeChat's API. If the token is missing or only whitespace, construction fails immediately with this error.","triggerScenarios":"Calling weixin.New(opts) (or starting cc-connect with a [platform.weixin] config block) where opts[\"token\"] is absent, an empty string, or whitespace only.","commonSituations":"config.toml omits the token field; token defined under the wrong platform section; environment-variable substitution produced an empty string; typos like \"Token\" or \"api_key\" instead of \"token\".","solutions":["Set token = \"<ilink bot Bearer token>\" in the weixin platform config","Verify the config key is exactly \"token\" and under the weixin platform section","Check that any env-var interpolation for the token resolves to a non-empty value"],"exampleFix":"// before\nerr := weixin.New(map[string]any{\"base_url\": \"https://ilink.ai\"})\n// after\nerr := weixin.New(map[string]any{\"base_url\": \"https://ilink.ai\", \"token\": os.Getenv(\"WEIXIN_TOKEN\")})","handlingStrategy":"validation","validationCode":"tok, _ := opts[\"token\"].(string)\nif strings.TrimSpace(tok) == \"\" {\n    return errors.New(\"weixin platform requires a non-empty token\")\n}\n_ = weixin.New(opts)","typeGuard":null,"tryCatchPattern":"p, err := weixin.New(opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"token is required\") {\n        log.Fatal(\"missing weixin token in config\")\n    }\n    return err\n}","preventionTips":["Keep token in config.toml under the weixin platform section","Load it from an env var and fail fast at startup if empty","Never rename the key to Token/api_key","Validate config before daemon start"],"tags":["go","config","weixin","authentication"],"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"}