{"record":{"id":"737c5b07059eb80d","repo":"plandex-ai/plandex","slug":"purpose-is-required","errorCode":null,"errorMessage":"purpose is required","messagePattern":"purpose is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/model/model_request.go","lineNumber":78,"sourceCode":"\tmessages := params.Messages\n\tprediction := params.Prediction\n\tstop := params.Stop\n\ttools := params.Tools\n\ttoolChoice := params.ToolChoice\n\tmodelConfig := params.ModelConfig\n\tmodelStreamId := params.ModelStreamId\n\tconvoMessageId := params.ConvoMessageId\n\tbuildId := params.BuildId\n\tmodelPackName := params.ModelPackName\n\tpurpose := params.Purpose\n\tsessionId := params.SessionId\n\tsettings := params.Settings\n\torgUserConfig := params.OrgUserConfig\n\tcurrentOrgId := auth.OrgId\n\tcurrentUserId := auth.User.Id\n\n\tif purpose == \"\" {\n\t\treturn nil, fmt.Errorf(\"purpose is required\")\n\t}\n\n\tbaseModelConfig := modelConfig.GetBaseModelConfig(authVars, settings, orgUserConfig)\n\n\tmessages = FilterEmptyMessages(messages)\n\tmessages = CheckSingleSystemMessage(modelConfig, baseModelConfig, messages)\n\tinputTokensEstimate := GetMessagesTokenEstimate(messages...) + TokensPerRequest\n\n\tconfig := modelConfig.GetRoleForInputTokens(inputTokensEstimate, settings)\n\tmodelConfig = &config\n\n\tif params.EstimatedOutputTokens != 0 {\n\t\tconfig = modelConfig.GetRoleForOutputTokens(params.EstimatedOutputTokens, settings)\n\t\tmodelConfig = &config\n\t}\n\n\tlog.Println(\"ModelRequest - modelConfig:\")\n\tspew.Dump(modelConfig)","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/model_request.go#L60-L96","documentation":"ModelRequest was invoked with an empty purpose parameter. purpose selects/describes the model request use-case and is mandatory; the library validates it up front before building model config and messages. This is a caller-side input validation error, not a provider error.","triggerScenarios":"Any call to ModelRequest with purpose == \"\" — e.g. GenPlanName, GenPipedDataName, GenNoteName, buildValidate, buildWholeFileFallback, or genPlanDescription passing an uninitialized/empty purpose string.","commonSituations":"Refactored call sites forgetting to set purpose; purpose derived from user input or config that is empty; a new helper built on ModelRequest omitting the field; empty DB/config value propagated into the call.","solutions":["Pass a non-empty purpose string at the call site","Trace which caller (GenPlanName, buildValidate, etc.) passed the empty value","Add validation at your own boundary before calling ModelRequest","Check config/DB values feeding purpose for emptiness","Document required purpose values for new wrappers around ModelRequest"],"exampleFix":"// before\nres, err := model.ModelRequest(ctx, auth, \"\", messages, params)\n// after\npurpose := \"generate_plan_name\"\nif purpose == \"\" { return nil, errors.New(\"purpose missing\") }\nres, err := model.ModelRequest(ctx, auth, purpose, messages, params)","handlingStrategy":"validation","validationCode":"if purpose == \"\" {\n    return nil, errors.New(\"purpose must be set before calling ModelRequest\")\n}","typeGuard":null,"tryCatchPattern":"res, err := model.ModelRequest(ctx, auth, purpose, messages, params)\nif err != nil {\n    if strings.Contains(err.Error(), \"purpose is required\") {\n        return nil, fmt.Errorf(\"caller bug: purpose not provided: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Define purpose as a typed constant/enum so it can't be an empty string","Validate purpose at your API boundary before reaching ModelRequest","Review all wrappers (GenPlanName, buildValidate, ...) for purpose propagation","Add a unit test asserting each wrapper passes a non-empty purpose"],"tags":["validation","api-misuse","required-parameter"],"backgroundTag":"missing-required-argument","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}