{"record":{"id":"8d2be82b13de83a9","repo":"mudler/LocalAI","slug":"no-job-id-returned-from-server-8d2be8","errorCode":null,"errorMessage":"No job ID returned from server","messagePattern":"No job ID returned from server","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/http/views/model-editor.html","lineNumber":910,"sourceCode":"                let successMsg = 'Import started! Tracking progress...';\n                if (hasSize || hasVram) {\n                    const parts = [];\n                    if (hasSize) parts.push('Size: ' + result.estimated_size_display);\n                    if (hasVram) parts.push('VRAM: ' + result.estimated_vram_display);\n                    successMsg += ' (' + parts.join(' · ') + ')';\n                }\n\n                if (result.uuid) {\n                    this.currentJobId = result.uuid;\n                    this.showAlert('success', successMsg);\n                    this.startJobPolling();\n                } else if (result.ID) {\n                    // Fallback for different response format\n                    this.currentJobId = result.ID;\n                    this.showAlert('success', successMsg);\n                    this.startJobPolling();\n                } else {\n                    throw new Error('No job ID returned from server');\n                }\n            } catch (error) {\n                this.showAlert('error', 'Failed to start import: ' + error.message);\n                this.isSubmitting = false;\n            }\n        },\n        \n        startJobPolling() {\n            if (this.jobPollInterval) {\n                clearInterval(this.jobPollInterval);\n            }\n            \n            this.jobPollInterval = setInterval(async () => {\n                if (!this.currentJobId) {\n                    clearInterval(this.jobPollInterval);\n                    return;\n                }\n                ","sourceCodeStart":892,"sourceCodeEnd":928,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/http/views/model-editor.html#L892-L928","documentation":"Thrown by the legacy model-editor UI's import submit when the import-job response contains neither result.uuid nor result.ID, so the client has no job identifier to poll (startJobPolling is only started when an ID exists). isSubmitting is reset in the catch so the form becomes usable again.","triggerScenarios":"POST to the import endpoint returns 200 with an unexpected body shape — e.g. an error envelope {error: ...} with success omitted, a proxied/HTML response parsed as JSON-without-id, or a server version whose import route returns a different field name.","commonSituations":"Version skew between the static model-editor.html view and a newer/older API; reverse proxy returning an HTML error page with 200; import rejected immediately (validation) so no job was ever created.","solutions":["Inspect the import POST response body in devtools to see what was actually returned","If it is an error envelope, address the underlying import error (bad tarball, unknown backend)","If a proxy HTML page, fix proxy routing for the import endpoint","If version skew, re-fetch the model-editor.html asset (hard reload) to match the server"],"exampleFix":"// before\n} else {\n    throw new Error('No job ID returned from server');\n}\n\n// after: include whatever came back\n} else {\n    throw new Error('No job ID returned from server: ' + JSON.stringify(result).slice(0, 200));\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isImportJob(result) {\n  return !!result && typeof result === 'object'\n    && (typeof result.uuid === 'string' && result.uuid.length > 0\n        || typeof result.ID === 'string' && result.ID.length > 0)\n}","tryCatchPattern":"try {\n  const result = await response.json()\n  if (!isImportJob(result)) {\n    throw new Error('Unexpected import response: ' + JSON.stringify(result).slice(0, 200))\n  }\n  this.currentJobId = result.uuid || result.ID\n  this.startJobPolling()\n} catch (error) {\n  this.showAlert('error', 'Failed to start import: ' + error.message)\n  this.isSubmitting = false\n}","preventionTips":["Hard-reload the legacy model-editor.html after a server upgrade so its JS matches the API contract","Log the raw response body when the id fields are missing — silent shape drift is the usual cause","Ensure the proxy passes JSON error envelopes through untouched instead of HTML pages"],"tags":["import","job-polling","legacy-ui","api-contract"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}