{"record":{"id":"6aa78a8a3cd77382","repo":"chenhg5/cc-connect","slug":"line-create-api-client-w","errorCode":null,"errorMessage":"line: create api client: %w","messagePattern":"line: create api client: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/line/line.go","lineNumber":78,"sourceCode":"\n\tcore.CheckAllowFrom(\"line\", allowFrom)\n\treturn &Platform{\n\t\tchannelSecret: secret,\n\t\tchannelToken:  token,\n\t\tallowFrom:     allowFrom,\n\t\tport:          port,\n\t\tcallbackPath:  path,\n\t}, nil\n}\n\nfunc (p *Platform) Name() string { return \"line\" }\n\nfunc (p *Platform) Start(handler core.MessageHandler) error {\n\tp.handler = handler\n\n\tbot, err := messaging_api.NewMessagingApiAPI(p.channelToken)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"line: create api client: %w\", err)\n\t}\n\tp.bot = bot\n\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(p.callbackPath, p.webhookHandler)\n\n\tp.server = &http.Server{\n\t\tAddr:    \":\" + p.port,\n\t\tHandler: mux,\n\t}\n\n\tgo func() {\n\t\tslog.Info(\"line: webhook server listening\", \"port\", p.port, \"path\", p.callbackPath)\n\t\tif err := p.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n\t\t\tslog.Error(\"line: server error\", \"error\", err)\n\t\t}\n\t}()\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/line/line.go#L60-L96","documentation":"Platform.Start creates a LINE Messaging API client via messaging_api.NewMessagingApiAPI(channelToken) and wraps any failure in this error. The LINE SDK returns an error when it cannot construct the client, most commonly because the channel token is empty or malformed. Start aborts and returns without starting the webhook HTTP server.","triggerScenarios":"Calling Start with p.channelToken empty or invalid so the SDK's client constructor fails (token validation/rejection at construction time).","commonSituations":"Placeholder token left in config; token copied with whitespace/newline; token revoked or from the wrong channel; SDK version change making token validation stricter.","solutions":["Verify channel_token in config is a valid long-lived channel access token from the LINE Developers Console.","Trim whitespace/newlines from the token value.","Issue a fresh token if the current one was revoked or expired.","Check the line-bot-sdk-go version for changed constructor behavior; pin a known-good version."],"exampleFix":"// before\np.channelToken = os.Getenv(\"LINE_TOKEN\") // empty if unset\n// after\ntoken := strings.TrimSpace(os.Getenv(\"LINE_TOKEN\"))\nif token == \"\" {\n    return fmt.Errorf(\"line: LINE_TOKEN is not set\")\n}\np.channelToken = token","handlingStrategy":"validation","validationCode":"// Go: check token before Start\nif strings.TrimSpace(cfg.Token) == \"\" {\n    return errors.New(\"line: channel_token must be set before Start\")\n}\nif !strings.HasPrefix(cfg.Token, \"eyJ\") { // LINE channel access tokens are JWT-like\n    return errors.New(\"line: channel_token does not look like a LINE access token\")\n}","typeGuard":null,"tryCatchPattern":"// Go: wrap Start failure with context\nif err := platform.Start(handler); err != nil {\n    if strings.Contains(err.Error(), \"create api client\") {\n        return fmt.Errorf(\"line platform failed to start: bad or revoked channel token: %w\", err)\n    }\n    return err\n}","preventionTips":["Trim and sanity-check the token at config load time.","Rotate tokens before expiry; revoked tokens fail at client creation.","Pin the line-bot-sdk-go version and read its changelog on upgrades.","Verify the token belongs to the same channel as channel_secret."],"tags":["line","sdk","authentication"],"backgroundTag":"api-request-failed","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"}