{"record":{"id":"78254feb36919125","repo":"SillyTavern/SillyTavern","slug":"connection-manager-is-not-available","errorCode":null,"errorMessage":"Connection Manager is not available","messagePattern":"Connection Manager is not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"public/scripts/extensions/shared.js","lineNumber":424,"sourceCode":"     * @param {string} profileId\n     * @param {string | (import('../custom-request.js').ChatCompletionMessage & {ignoreInstruct?: boolean})[]} prompt\n     * @param {number} maxTokens\n     * @param {Object} custom\n     * @param {boolean?} [custom.stream=false]\n     * @param {AbortSignal?} [custom.signal]\n     * @param {boolean?} [custom.extractData=true]\n     * @param {boolean?} [custom.includePreset=true]\n     * @param {boolean?} [custom.includeInstruct=true]\n     * @param {Partial<InstructSettings>?} [custom.instructSettings] Override instruct settings\n     * @param {Record<string, any>} [overridePayload] - Override payload for the request\n     * @returns {Promise<import('../custom-request.js').ExtractedData | (() => AsyncGenerator<import('../custom-request.js').StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator\n     */\n    static async sendRequest(profileId, prompt, maxTokens, custom = this.defaultSendRequestParams, overridePayload = {}) {\n        const { stream, signal, extractData, includePreset, includeInstruct, instructSettings } = { ...this.defaultSendRequestParams, ...custom };\n\n        const context = SillyTavern.getContext();\n        if (context.extensionSettings.disabledExtensions.includes('connection-manager')) {\n            throw new Error('Connection Manager is not available');\n        }\n\n        const profile = this.getProfile(profileId);\n        const selectedApiMap = this.validateProfile(profile);\n\n        try {\n            switch (selectedApiMap.selected) {\n                case 'openai': {\n                    if (!selectedApiMap.source) {\n                        throw new Error(`API type ${selectedApiMap.selected} does not support chat completions`);\n                    }\n\n                    const proxyPreset = proxies.find((p) => p.name === profile.proxy);\n\n                    const messages = Array.isArray(prompt) ? prompt : [{ role: 'user', content: prompt }];\n                    return await context.ChatCompletionService.processRequest({\n                        stream,\n                        messages,","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/SillyTavern/SillyTavern/blob/8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8/public/scripts/extensions/shared.js#L406-L442","documentation":"Thrown by ConnectionManagerRequestService.sendRequest() when 'connection-manager' is present in context.extensionSettings.disabledExtensions. The Connection Manager is a core extension that owns connection profiles; when disabled, profile-based requests cannot proceed because there is no profile source to read. This is an environment/extension-state guard, not a network error.","triggerScenarios":"Calling ConnectionManagerRequestService.sendRequest(profileId, ...) while the user (or an admin policy) has disabled the Connection Manager extension. The check at line 423 fires before profile lookup.","commonSituations":"User disabled Connection Manager in Extensions panel; a migration or reset marked it disabled by default; conflict with a legacy connection extension that auto-disables it; calling the API from an extension that does not first check availability via getSupportedProfiles().","solutions":["Re-enable the Connection Manager extension in User Settings > Extensions.","Before calling sendRequest, guard with getSupportedProfiles() in a try/catch (it throws the same error) or check context.extensionSettings.disabledExtensions directly.","If the user intentionally disabled it, fall back to direct ChatCompletion/TextCompletion service calls without a profile."],"exampleFix":"// before\nconst data = await ConnectionManagerRequestService.sendRequest(profileId, prompt, 512);\n// after\nconst ctx = SillyTavern.getContext();\nif (ctx.extensionSettings.disabledExtensions.includes('connection-manager')) {\n  toastr.warning('Enable the Connection Manager extension to use profiles.');\n  return;\n}\nconst data = await ConnectionManagerRequestService.sendRequest(profileId, prompt, 512);","handlingStrategy":"validation","validationCode":"function isConnectionManagerEnabled() {\n  const ctx = SillyTavern.getContext();\n  return !ctx.extensionSettings.disabledExtensions.includes('connection-manager');\n}\nif (!isConnectionManagerEnabled()) {\n  toastr.warning('Enable the Connection Manager extension to use profile-based requests.');\n}","typeGuard":"function connectionManagerAvailable(): boolean {\n  return !SillyTavern.getContext().extensionSettings.disabledExtensions.includes('connection-manager');\n}","tryCatchPattern":"try { return await ConnectionManagerRequestService.sendRequest(id, prompt, 512); }\ncatch (e) {\n  if (e.message === 'Connection Manager is not available') { toastr.warning('Enable Connection Manager.'); return null; }\n  throw e;\n}","preventionTips":["Check disabledExtensions before calling any ConnectionManagerRequestService method.","Offer getSupportedProfiles() in a try/catch as a feature-detection probe before showing profile-based UI."],"tags":["connection-manager","extension","configuration","validation"],"backgroundTag":null,"analyzedSha":"8172dcd0ee672d3cd9a5e5f7af134f91a45cd2b8","analyzedAt":"2026-08-13T07:48:40.832Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}