{"record":{"id":"7ca4b5194f1d8b95","repo":"Billionmail/BillionMail","slug":"failed-to-set-http-verification","errorCode":null,"errorMessage":"Failed to set HTTP verification: {}","messagePattern":"Failed to set HTTP verification: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/acme/acme.go","lineNumber":401,"sourceCode":"\n\t// Get configuration\n\tconfig := GetConfig(myUser)\n\tif config == nil {\n\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to get configuration\"))\n\t}\n\n\tclient, err := lego.NewClient(config)\n\tif err != nil {\n\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to create ACME client: {}\", err.Error()))\n\t}\n\n\t// Set verification method\n\tif vtype == \"http\" {\n\t\t// Assume the HTTP server is already running and properly configured\n\t\t// to handle the challenge requests\n\t\terr = client.Challenge.SetHTTP01Provider(http01.NewProviderServer(\"127.0.0.1\", \"60880\"))\n\t\tif err != nil {\n\t\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to set HTTP verification: {}\", err.Error()))\n\t\t}\n\t} else if vtype == \"dns\" && dnsProvider != \"\" {\n\t\t// Set DNS verification - same as in the standard ApplySSL function\n\t\tswitch dnsProvider {\n\t\tcase \"tencentcloud\":\n\t\t\terr = SetDnsTencentcloud(ctx, client, dnsProviderToken)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to set Tencent Cloud DNS verification: {}\", err.Error()))\n\t\t\t}\n\t\tcase \"alidns\":\n\t\t\terr = SetDnsAliyun(ctx, client, dnsProviderToken)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to set Alibaba Cloud DNS verification: {}\", err.Error()))\n\t\t\t}\n\t\tcase \"cloudxns\":\n\t\t\terr = SetDnsCloudxns(ctx, client, dnsProviderToken)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", \"\", errors.New(public.LangCtx(ctx, \"Failed to set CloudXNS DNS verification: {}\", err.Error()))","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/acme/acme.go#L383-L419","documentation":"ApplySSLWithExistingServer configures a lego ACME client to solve the HTTP-01 challenge by registering a custom provider bound to 127.0.0.1:60880 via client.Challenge.SetHTTP01Provider. The error wraps any failure returned by lego when installing that provider. In lego this call essentially cannot fail for the built-in http01.ProviderServer, so hitting it indicates a programming bug, a nil client, or a forked/modified lego version whose SetHTTP01Provider performs extra validation.","triggerScenarios":"Calling ApplySSLWithExistingServer (via Apply, StartRenew, ApplyLetsEncryptCertWithHttp, or ApplyConsoleCert) with vtype == \"http\" while client.Challenge is nil/nil-initialized, or using a lego version where SetHTTP01Provider returns an error.","commonSituations":"Custom builds of lego with extra provider validation; a client constructed incorrectly (missing user key so Challenge chain misbehaves); copy-pasted code that nils out the Challenge map before this call.","solutions":["Inspect the wrapped err.Error() in the message; if it is empty or nil-related, verify the lego ACME client is constructed with a valid user private key before ApplySSLWithExistingServer is called","Pin lego to the version upstream BillionMail was built against (go.mod) so SetHTTP01Provider matches the expected no-error behavior","If running custom challenge logic, ensure the HTTP server actually listens on 127.0.0.1:60880 before requesting the certificate, since the challenge will fail later otherwise"],"exampleFix":"// before\nclient, err := lego.NewClient(lego.NewConfig())\nerr = client.Challenge.SetHTTP01Provider(http01.NewProviderServer(\"127.0.0.1\", \"60880\"))\n// after\nclient, err := lego.NewClient(lego.NewConfigForUser(myUser)) // valid key loaded\nif err != nil { return \"\", \"\", err }\nerr = client.Challenge.SetHTTP01Provider(http01.NewProviderServer(\"127.0.0.1\", \"60880\"))","handlingStrategy":"try-catch","validationCode":"if client == nil || client.Challenge == nil {\n    return fmt.Errorf(\"ACME client not initialized before SetHTTP01Provider\")\n}\n// also ensure the challenge port is free:\nif ln, err := net.Listen(\"tcp\", \"127.0.0.1:60880\"); err != nil {\n    return fmt.Errorf(\"port 60880 already in use: %w\", err)\n} else { ln.Close() }","typeGuard":"func acmeClientReady(c *lego.Client) bool { return c != nil && c.Challenge != nil }","tryCatchPattern":"cert, _, err := ApplySSLWithExistingServer(ctx, ...)\nif err != nil {\n    if strings.Contains(err.Error(), \"Failed to set HTTP verification\") {\n        log.Printf(\"challenge provider setup failed: %v\", err) // inspect lego cause\n    }\n    return err\n}","preventionTips":["Always construct the lego client with a valid user key before setting providers","Pin the lego dependency version in go.mod to avoid behavioral drift","Confirm port 60880 is free and the HTTP server is up before requesting http-01 certificates"],"tags":["acme","ssl","http-01","lego"],"backgroundTag":"acme-challenge-setup-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}