{"record":{"id":"cbac24dfccabf7ac","repo":"Billionmail/BillionMail","slug":"claude-script-generation-w","errorCode":null,"errorMessage":"claude script generation: %w","messagePattern":"claude script generation: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/video_gen/script.go","lineNumber":160,"sourceCode":"\t\tseconds = 1\n\t}\n\treturn seconds\n}\n\n// GenerateScript calls Claude API to generate a personalized video script.\nfunc GenerateScript(ctx context.Context, cfg ScriptConfig, input ScriptInput) (*ScriptOutput, error) {\n\tconfig := openai.DefaultConfig(cfg.APIKey)\n\tconfig.BaseURL = cfg.scriptBaseURL()\n\tclient := openai.NewClientWithConfig(config)\n\n\tresp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{\n\t\tModel:               cfg.Model,\n\t\tMessages:            BuildScriptMessages(input),\n\t\tMaxCompletionTokens: maxScriptTokens,\n\t\tTemperature:         0.7,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"claude script generation: %w\", err)\n\t}\n\n\tif len(resp.Choices) == 0 {\n\t\treturn nil, fmt.Errorf(\"claude returned no choices\")\n\t}\n\n\tscript := strings.TrimSpace(resp.Choices[0].Message.Content)\n\treturn &ScriptOutput{\n\t\tScript:   script,\n\t\tDuration: EstimateDuration(script),\n\t}, nil\n}\n","sourceCodeStart":142,"sourceCodeEnd":173,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/video_gen/script.go#L142-L173","documentation":"GenerateScript calls the Claude (Anthropic-compatible) chat completion API to produce a sales script. If the API client returns an error (HTTP failure, auth failure, rate limit, connection error), it is wrapped with 'claude script generation: %w'.","triggerScenarios":"The chat completion request fails: invalid/missing API key, HTTP 429 rate limit, 5xx from the provider, network failure, or ctx cancellation before the response arrives.","commonSituations":"ANTHROPIC/LLM API key not set or expired in the deployment; monthly quota or rate limit exhausted during bulk campaign runs; model name typo; network egress blocked from the container.","solutions":["Read the wrapped cause for the HTTP status / API error body","Verify the LLM API key is present, valid, and has quota (check provider dashboard)","Implement retry with exponential backoff for 429/5xx responses","Confirm the model name in cfg.Model is one the account can access"],"exampleFix":"// before\nresp, err := client.Chat(ctx, req)\nif err != nil {\n\treturn nil, fmt.Errorf(\"claude script generation: %w\", err)\n}\n// after\nresp, err := client.Chat(ctx, req)\nif err != nil {\n\tvar apiErr *openai.APIError\n\tif errors.As(err, &apiErr) && apiErr.HTTPStatusCode == 429 {\n\t\ttime.Sleep(backoff)\n\t\treturn generateScriptWithRetry(ctx, cfg, input)\n\t}\n\treturn nil, fmt.Errorf(\"claude script generation: %w\", err)\n}","handlingStrategy":"retry","validationCode":"if cfg.APIKey == \"\" {\n\treturn fmt.Errorf(\"LLM API key not configured\")\n}\nif cfg.Model == \"\" {\n\treturn fmt.Errorf(\"LLM model not configured\")\n}","typeGuard":"func isRetryableLLMError(err error) bool {\n\tvar apiErr interface{ HTTPStatusCode() int }\n\tif errors.As(err, &apiErr) {\n\t\tcode := apiErr.HTTPStatusCode()\n\t\treturn code == 429 || code >= 500\n\t}\n\treturn errors.Is(err, context.DeadlineExceeded)\n}","tryCatchPattern":"script, err := GenerateScript(ctx, cfg, input)\nvar apiErr *APIError\nif errors.As(err, &apiErr) && apiErr.HTTPStatusCode == 429 {\n\ttime.Sleep(exponentialBackoff(attempt))\n\treturn GenerateScript(ctx, cfg, input)\n}","preventionTips":["Set and verify the LLM API key in every environment before campaigns run","Implement exponential backoff for 429/5xx on all LLM calls","Throttle bulk campaign generation to stay under provider rate limits","Pin cfg.Model to a model your account has access to"],"tags":["llm","api-error","rate-limit","network","claude"],"backgroundTag":"llm-api-error","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}