{"record":{"id":"4214bb7dd910b927","repo":"Tencent/WeKnora","slug":"parse-telegram-credentials-w","errorCode":null,"errorMessage":"parse telegram credentials: %w","messagePattern":"parse telegram credentials: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/im/telegram/factory.go","lineNumber":17,"sourceCode":"package telegram\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/Tencent/WeKnora/internal/im\"\n\t\"github.com/Tencent/WeKnora/internal/logger\"\n)\n\n// NewFactory returns an im.AdapterFactory for Telegram bot channels.\n// Supports \"webhook\" and \"websocket\" (long polling, default).\nfunc NewFactory() im.AdapterFactory {\n\treturn func(factoryCtx context.Context, channel *im.IMChannel, msgHandler func(context.Context, *im.IncomingMessage) error) (im.Adapter, context.CancelFunc, error) {\n\t\tcreds, err := im.ParseCredentials(channel.Credentials)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"parse telegram credentials: %w\", err)\n\t\t}\n\n\t\tbotToken := im.GetString(creds, \"bot_token\")\n\n\t\tmode := im.ResolveMode(channel, \"websocket\")\n\n\t\tswitch mode {\n\t\tcase \"webhook\":\n\t\t\tsecretToken := im.GetString(creds, \"secret_token\")\n\t\t\tadapter := NewWebhookAdapter(botToken, secretToken)\n\t\t\treturn adapter, nil, nil\n\n\t\tcase \"websocket\":\n\t\t\tclient := NewLongConnClient(botToken, msgHandler)\n\n\t\t\twsCtx, wsCancel := context.WithCancel(context.Background())\n\t\t\tgo func() {\n\t\t\t\tif err := client.Start(wsCtx); err != nil && wsCtx.Err() == nil {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/im/telegram/factory.go#L1-L35","documentation":"The Telegram adapter factory parses channel.Credentials via im.ParseCredentials before building the bot client; malformed credentials JSON/structure causes construction to fail with this wrapped error, preserving the underlying parse error via %w.","triggerScenarios":"Creating a Telegram channel whose Credentials field is not valid JSON (or not the expected string map) — e.g. empty credentials, single-quoted JSON, or a non-JSON secret value.","commonSituations":"Pasting a bot token with stray whitespace/newlines into a non-JSON field; storing credentials as YAML instead of JSON; migrating channels where the credentials column was left empty; secrets manager returning a raw token instead of a JSON object.","solutions":["Ensure channel.Credentials is valid JSON, e.g. {\"bot_token\":\"123:ABC\"}","Check the wrapped inner error (errors.Unwrap / %v of the cause) for the exact parse failure","Fix the secret/config source so it emits a JSON object, not a bare token"],"exampleFix":"// before\ncredentials: \"123456:ABC-DEF\"\n// after\ncredentials: \"{\\\"bot_token\\\":\\\"123456:ABC-DEF\\\"}\"","handlingStrategy":"validation","validationCode":"var creds map[string]string\nif err := json.Unmarshal([]byte(channel.Credentials), &creds); err != nil {\n    return fmt.Errorf(\"telegram credentials must be a JSON object: %w\", err)\n}\nif creds[\"bot_token\"] == \"\" {\n    return errors.New(\"telegram credentials missing bot_token\")\n}","typeGuard":null,"tryCatchPattern":"adapter, cancel, err := telegram.NewFactory()(ctx, ch, handler)\nif err != nil {\n    var perr error\n    if errors.As(err, &perr) { /* inspect unwrapped parse cause */ }\n    log.Printf(\"telegram channel %s: %v\", ch.ID, err)\n}","preventionTips":["Store credentials as JSON objects ({\"bot_token\":\"...\"}), never bare tokens","Validate credentials JSON when the channel is created, before saving","Ensure secret managers emit the full JSON object, not just the token string"],"tags":["telegram","credentials","parse-error"],"backgroundTag":"credentials-parse-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}