{"record":{"id":"46301492e7dd301a","repo":"vxcontrol/pentagi","slug":"failed-to-call-llm-after-d-retries-w","errorCode":null,"errorMessage":"failed to call llm after %d retries: %w","messagePattern":"failed to call llm after (.+?) retries: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/providers/providers.go","lineNumber":1090,"sourceCode":"// assistant bootstrap (docker image, language, and title selection) with the\n// same short retry-with-backoff already used for the agent execution loop\n// (see performSimpleChain/callWithRetries), so one transient error from the\n// LLM gateway (e.g. a bad gateway from a litellm proxy) does not fail flow or\n// assistant creation outright.\nfunc callWithSetupRetries(\n\tctx context.Context,\n\tprv provider.Provider,\n\topt pconfig.ProviderOptionsType,\n\tprompt string,\n) (string, error) {\n\tvar (\n\t\tresult string\n\t\terr    error\n\t)\n\n\tfor idx := 0; idx <= maxRetriesToCallSimpleChain; idx++ {\n\t\tif idx == maxRetriesToCallSimpleChain {\n\t\t\treturn \"\", fmt.Errorf(\"failed to call llm after %d retries: %w\", idx, err)\n\t\t}\n\n\t\tresult, err = prv.Call(ctx, opt, prompt)\n\t\tif err == nil {\n\t\t\treturn result, nil\n\t\t}\n\n\t\tif errors.Is(err, context.Canceled) {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn \"\", ctx.Err()\n\t\tcase <-time.After(delayBetweenRetries):\n\t\t}\n\t}\n","sourceCodeStart":1072,"sourceCodeEnd":1108,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/providers/providers.go#L1072-L1108","documentation":"callWithSetupRetries calls prv.Call up to maxRetriesToCallSimpleChain times with backoff; when every attempt fails it wraps the last error in this message. The wrapped error holds the final underlying failure (auth, network, rate limit, content filter, etc.).","triggerScenarios":"NewFlowProvider / NewAssistantProvider LLM calls where all retries fail: persistent 401/403, exhausted quota, unreachable endpoint, context deadline exceeded, or a deterministic model error that no retry can fix.","commonSituations":"Invalid API key; account out of credits; provider outage; prompt consistently rejected (too long, content policy); network egress blocked in a containerized deployment.","solutions":["Inspect the wrapped final error for the HTTP status or cause of the last Call.","Verify credentials and account quota with the provider directly.","Check network egress/proxy from the backend container to the provider endpoint.","If deterministic (e.g. context length exceeded), fix the prompt/model config — retrying won't help.","Increase resilience: retry only applies to transient errors; consider a fallback provider."],"exampleFix":"// before: all attempts 401\npc.cfg.OpenAIAPIKey = \"\" // stale key\n// after\npc.cfg.OpenAIAPIKey = os.Getenv(\"OPENAI_API_KEY\") // valid key; calls succeed on first attempt","handlingStrategy":"retry","validationCode":"if prv == nil || ctx.Err() != nil {\n    return \"\", fmt.Errorf(\"provider not ready or context canceled before call\")\n}","typeGuard":"null","tryCatchPattern":"result, err := callWithSetupRetries(ctx, prv, opt, prompt)\nif err != nil {\n    var final error\n    if errors.As(err, &final) {\n        log.Printf(\"LLM call failed permanently: %v\", final) // inspect last Call error\n    }\n    if ctx.Err() != nil {\n        return ctx.Err()\n    }\n    return err\n}","preventionTips":["Validate credentials/quota before entering retry loops.","Only retry transient errors; fail fast on 401/400-class errors.","Set realistic context deadlines so retries have time to succeed.","Configure a fallback provider chain for critical paths."],"tags":["llm","retry","network","api-call"],"backgroundTag":"llm-call-failed-after-retries","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}