{"record":{"id":"f6812af0732c8fba","repo":"weaviate/weaviate","slug":"classification-put-w","errorCode":null,"errorMessage":"classification: put: %w","messagePattern":"classification: put: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"usecases/classification/classifier.go","lineNumber":177,"sourceCode":"\t\treturn nil, err\n\t}\n\n\terr = NewValidator(c.classGetterWithAuthzFunc(ctx, principal), params).Do()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := c.assignNewID(&params); err != nil {\n\t\treturn nil, fmt.Errorf(\"classification: assign id: %w\", err)\n\t}\n\n\tparams.Status = models.ClassificationStatusRunning\n\tparams.Meta = &models.ClassificationMeta{\n\t\tStarted: strfmt.DateTime(time.Now()),\n\t}\n\n\tif err := c.repo.Put(ctx, params); err != nil {\n\t\treturn nil, fmt.Errorf(\"classification: put: %w\", err)\n\t}\n\n\t// asynchronously trigger the classification\n\tfilters, err := c.extractFilters(ctx, principal, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tenterrors.GoWrapper(func() { c.run(params, filters) }, c.logger)\n\n\treturn &params, nil\n}\n\nfunc (c *Classifier) extractFilters(ctx context.Context, principal *models.Principal, params models.Classification) (Filters, error) {\n\tif params.Filters == nil {\n\t\treturn classificationFilters{}, nil\n\t}\n","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/classification/classifier.go#L159-L195","documentation":"Schedule() persists the new classification job (status 'running') into the classification repository via repo.Put before triggering the async run. This error wraps that storage write failure. The classification was never started, so the caller gets an error instead of a job id they can poll.","triggerScenarios":"The classification store write fails during POST /v1/classifications: the underlying schema/object store returns an error (cluster consensus unavailable, node unhealthy, storage I/O failure, context deadline exceeded).","commonSituations":"Cluster in a degraded state (leader election in progress, RAFT unavailable); node disk full; store timeouts under heavy load; the request context cancelled by an aggressive client timeout before the write completes.","solutions":["Retry the classification scheduling request once the cluster is healthy.","Check cluster health (GET /v1/nodes) — verify all nodes are up and RAFT/consensus is stable.","Check node disk space and storage backend health on the coordinator node.","Increase the client request timeout so the store write is not cancelled mid-flight.","Inspect the wrapped error to determine whether it is a timeout, consensus, or I/O failure and address accordingly."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const health = await (await fetch('http://localhost:8080/v1/nodes')).json();\nconst allHealthy = health.nodes?.every(n => n.status === 'HEALTHY');\nif (!allHealthy) throw new Error('cluster unhealthy: resolve node status before scheduling classification');","typeGuard":null,"tryCatchPattern":"try {\n  await scheduleClassification(params);\n} catch (e) {\n  if (String(e).includes('classification: put')) {\n    await sleep(backoff);\n    return scheduleClassification(params); // retry after cluster recovers\n  }\n  throw e;\n}","preventionTips":["Check GET /v1/nodes for cluster health before issuing classification jobs.","Use client timeouts generous enough to cover the store write.","Monitor disk space and RAFT/consensus stability on coordinator nodes.","Retry idempotently: verify via GET /v1/classifications/{id} whether the job already exists before re-scheduling."],"tags":["classification","persistence","storage"],"backgroundTag":"storage-write-failed","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}