{"record":{"id":"f5eb7508ed61721f","repo":"bytebase/bytebase","slug":"failed-to-parse-phone-number","errorCode":null,"errorMessage":"failed to parse phone number","messagePattern":"failed to parse phone number","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/webhook/dingtalk/app.go","lineNumber":42,"sourceCode":"}\n\nfunc newProvider(id, secret, robot string) *provider {\n\treturn &provider{\n\t\tid:     id,\n\t\tsecret: secret,\n\t\trobot:  robot,\n\t\tc:      &http.Client{},\n\t}\n}\n\nfunc Validate(ctx context.Context, id, secret, robot, phone string) error {\n\tp := newProvider(id, secret, robot)\n\tif err := p.refreshToken(ctx); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to refresh token\")\n\t}\n\tmobile, err := getDingTalkMobileFromPhone(phone)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to parse phone number\")\n\t}\n\tid, err = p.getIDByPhone(ctx, mobile)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get user id by phone\")\n\t}\n\tif err := p.sendMessage(ctx, []string{id}, \"test\", \"test\"); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to send test message\")\n\t}\n\treturn nil\n}\n\nfunc (p *provider) refreshToken(ctx context.Context) error {\n\ttoken, err := getTokenCached(ctx, p.c, p.id, p.secret)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get token\")\n\t}\n\tp.token = token\n\treturn nil","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/webhook/dingtalk/app.go#L24-L60","documentation":"Validate parses a human phone number into DingTalk mobile format via getDingTalkMobileFromPhone before looking up the user ID; a malformed phone fails here. The wrap preserves the underlying parse error so the developer knows what format was rejected.","triggerScenarios":"validateIMSetting supplies a phone string missing a country code, containing spaces/dashes/parentheses, a non-digit extension, or an empty string, and getDingTalkMobileFromPhone cannot normalize it.","commonSituations":"Users entering local-format numbers (no +86) into DingTalk IM settings; copy-pasted numbers with formatting characters; phone fields bound to the wrong configuration value (e.g. a name instead of a number).","solutions":["Enter the phone in international format with country code, e.g. +8613800138000","Strip spaces, dashes, and parentheses before saving the webhook IM setting","Check getDingTalkMobileFromPhone's accepted pattern and normalize input accordingly","Confirm the phone number is actually registered with a DingTalk account"],"exampleFix":"// before\nphone := \"138-0013-8000\"\n// after\nphone := \"+8613800138000\"","handlingStrategy":"validation","validationCode":"re := regexp.MustCompile(`^\\+\\d{7,15}$`)\nif !re.MatchString(phone) { return errors.New(\"phone must be international format, e.g. +8613800138000\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate phone format at input time in the webhook settings form","Strip formatting characters (spaces, dashes) before saving","Always require the country code prefix"],"tags":["dingtalk","validation","phone-number","webhook"],"backgroundTag":"invalid-argument-format","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}