{"record":{"id":"b966d69f35989585","repo":"eyaltoledano/claude-task-master","slug":"base-url-is-required-for-openai-compatible-provide","errorCode":null,"errorMessage":"Base URL is required for OpenAI-compatible providers. Please provide a baseURL.","messagePattern":"Base URL is required for OpenAI-compatible providers\\. Please provide a baseURL\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/modules/task-manager/models.js","lineNumber":668,"sourceCode":"\t\t\t\t\t// Get current provider for this role to check if we should preserve baseURL\n\t\t\t\t\tlet currentProvider;\n\t\t\t\t\tif (role === 'main') {\n\t\t\t\t\t\tcurrentProvider = getMainProvider(projectRoot);\n\t\t\t\t\t} else if (role === 'research') {\n\t\t\t\t\t\tcurrentProvider = getResearchProvider(projectRoot);\n\t\t\t\t\t} else if (role === 'fallback') {\n\t\t\t\t\t\tcurrentProvider = getFallbackProvider(projectRoot);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only preserve baseURL if we're already using OPENAI_COMPATIBLE\n\t\t\t\t\tconst existingBaseURL =\n\t\t\t\t\t\tcurrentProvider === CUSTOM_PROVIDERS.OPENAI_COMPATIBLE\n\t\t\t\t\t\t\t? getBaseUrlForRole(role, projectRoot)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\tconst resolvedBaseURL = baseURL || existingBaseURL;\n\t\t\t\t\tif (!resolvedBaseURL) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Base URL is required for OpenAI-compatible providers. Please provide a baseURL.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\twarningMessage = `Warning: Custom OpenAI-compatible model '${modelId}' set with base URL '${resolvedBaseURL}'. Taskmaster cannot guarantee compatibility. Ensure your API endpoint follows the OpenAI API specification.`;\n\t\t\t\t\treport('warn', warningMessage);\n\t\t\t\t\t// Store the computed baseURL so it gets saved in config\n\t\t\t\t\tcomputedBaseURL = resolvedBaseURL;\n\t\t\t\t} else {\n\t\t\t\t\t// Invalid provider hint - should not happen with our constants\n\t\t\t\t\tthrow new Error(`Invalid provider hint received: ${providerHint}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// No hint provided (flags not used)\n\t\t\tif (modelData) {\n\t\t\t\t// Found internally, use the provider from the internal list\n\t\t\t\tdeterminedProvider = modelData.provider;\n\t\t\t\treport(","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/task-manager/models.js#L650-L686","documentation":"Thrown by setModel when the user sets a model with the --openai-compatible provider hint but no baseURL can be resolved. Unlike LM Studio, OpenAI-compatible providers have no sensible default endpoint, so the library refuses to save a config entry that would be unusable. The base URL must come from the --base-url flag or from an existing baseURL already stored for that role while the provider was already OPENAI_COMPATIBLE.","triggerScenarios":"Calling setModel (or `task-master models --set-main=<id> --openai-compatible`) with a custom model ID and the OPENAI_COMPATIBLE provider hint, where the --base-url flag is omitted AND the role's current provider is not already OPENAI_COMPATIBLE (so no existingBaseURL is preserved).","commonSituations":"First-time setup of a custom OpenAI-compatible endpoint (vLLM, LiteLLM proxy, Together, etc.) where the user forgot --base-url; switching from another provider (e.g. openrouter) to openai-compatible and assuming the old baseURL carries over — it deliberately does not; scripting the models command and dropping the flag.","solutions":["Pass the endpoint with --base-url, e.g. `task-master models --set-main=my-model --openai-compatible --base-url=https://my-endpoint/v1`","If the role already used an OpenAI-compatible provider, verify its baseURL exists in .taskmaster/config.json under models.<role>.baseURL so it can be preserved; otherwise set it explicitly","Use the LM Studio hint instead (it defaults to http://localhost:1234/v1) only if that is actually your setup","Programmatically, call setModel with baseURL in the options object"],"exampleFix":"// before\ntask-master models --set-main=llama-3-70b --openai-compatible\n// after\ntask-master models --set-main=llama-3-70b --openai-compatible --base-url=https://api.together.xyz/v1","handlingStrategy":"validation","validationCode":"import { getBaseUrlForRole } from './utils.js';\nfunction assertBaseURL(baseURL, role, projectRoot, currentProvider, CUSTOM_PROVIDERS) {\n  const existing = currentProvider === CUSTOM_PROVIDERS.OPENAI_COMPATIBLE\n    ? getBaseUrlForRole(role, projectRoot) : null;\n  if (!baseURL && !existing) {\n    throw new Error(`--base-url is required when setting an OpenAI-compatible model for role '${role}'`);\n  }\n}","typeGuard":"function hasBaseUrl(opts) {\n  return typeof opts.baseURL === 'string' && opts.baseURL.trim().length > 0;\n}","tryCatchPattern":"try {\n  await setModel(projectRoot, role, modelId, { providerHint: 'OPENAI_COMPATIBLE', baseURL });\n} catch (err) {\n  if (/Base URL is required/i.test(err.message)) {\n    console.error('Provide --base-url, e.g. --base-url=https://your-endpoint/v1');\n  } else throw err;\n}","preventionTips":["Always pair --openai-compatible with --base-url in scripts and docs","Keep baseURL persisted in .taskmaster/config.json for the role so repeat sets preserve it","Remember baseURL is only preserved when the role's current provider is already OPENAI_COMPATIBLE","Sanity-check the endpoint ends with the OpenAI-compatible path (often /v1)"],"tags":["configuration","provider","base-url","openai-compatible"],"backgroundTag":"missing-required-config-value","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}