{"record":{"id":"682fbe2a990a1d3d","repo":"micro/go-micro","slug":"ai-model-is-nil","errorCode":null,"errorMessage":"ai model is nil","messagePattern":"ai model is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/retry.go","lineNumber":147,"sourceCode":"}\n\n// GeneratePolicy controls timeout and retry behavior for a model call.\ntype GeneratePolicy struct {\n\tTimeout     time.Duration\n\tMaxAttempts int\n\tBackoff     time.Duration\n\t// Jitter adds up to this duration of random delay to retry backoff.\n\t// It is opt-in so existing retry timing remains deterministic by default.\n\tJitter time.Duration\n}\n\n// GenerateWithRetry calls m.Generate with per-attempt timeout and bounded retry.\nfunc GenerateWithRetry(ctx context.Context, m Model, req *Request, policy GeneratePolicy, opts ...GenerateOption) (*Response, error) {\n\tif policy.MaxAttempts <= 0 {\n\t\tpolicy.MaxAttempts = 1\n\t}\n\tif m == nil {\n\t\treturn nil, errors.New(\"ai model is nil\")\n\t}\n\n\tvar last error\n\tfor attempt := 1; attempt <= policy.MaxAttempts; attempt++ {\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tcallCtx := ctx\n\t\tcancel := func() {}\n\t\tif policy.Timeout > 0 {\n\t\t\tcallCtx, cancel = context.WithTimeout(ctx, policy.Timeout)\n\t\t}\n\t\tif info, ok := RunInfoFrom(callCtx); ok {\n\t\t\tinfo.Attempt = attempt\n\t\t\tinfo.MaxAttempts = policy.MaxAttempts\n\t\t\tcallCtx = WithRunInfo(callCtx, info)\n\t\t}","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/retry.go#L129-L165","documentation":"GenerateWithRetry validates its Model argument up front and returns this error immediately if m is nil, before any retry loop runs. It prevents a nil-pointer panic inside the retry/timeout machinery and surfaces the misconfiguration clearly.","triggerScenarios":"Calling ai.GenerateWithRetry with a nil Model — typically because model construction failed and the error was ignored, or a config lookup returned nil.","commonSituations":"Ignoring the error from provider/model factory functions; optional model config keys missing so the resolved model is nil; struct fields left zero because initialization is deferred or conditional.","solutions":["Check the error from model/provider construction before calling GenerateWithRetry","Verify the model configuration is loaded (provider name, API key, model id) so the factory returns a non-nil Model","Add a nil check at the call site: if m == nil { return error before retrying }"],"exampleFix":"// before\nmodel, _ := openai.New(cfg) // error ignored\nresp, err := ai.GenerateWithRetry(ctx, model, req, policy)\n// after\nmodel, err := openai.New(cfg)\nif err != nil {\n    return err\n}\nif model == nil {\n    return errors.New(\"model not configured\")\n}\nresp, err := ai.GenerateWithRetry(ctx, model, req, policy)","handlingStrategy":"validation","validationCode":"if model == nil {\n    return nil, errors.New(\"ai model not configured\")\n}\nresp, err := ai.GenerateWithRetry(ctx, model, req, policy)","typeGuard":"func modelReady(m ai.Model) bool { return m != nil }","tryCatchPattern":"resp, err := ai.GenerateWithRetry(ctx, model, req, policy)\nif err != nil && strings.Contains(err.Error(), \"ai model is nil\") {\n    return fmt.Errorf(\"model misconfigured: construction failed or config missing\")\n}","preventionTips":["Always check errors from model/provider constructors before use","Fail fast at startup if the configured model resolves to nil","Keep model construction in one place so nil models can't leak into call sites"],"tags":["go","ai","nil-pointer","configuration","validation"],"backgroundTag":"nil-argument","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}