{"record":{"id":"4732febeb93fd0ce","repo":"thanos-io/thanos","slug":"set-tenant","errorCode":null,"errorMessage":"set tenant","messagePattern":"set tenant","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/receive/writecapnp/marshal.go","lineNumber":69,"sourceCode":"\tif err != nil {\n\t\treturn WriteRequest{}, err\n\t}\n\tif err := wr.SetData(t); err != nil {\n\t\treturn WriteRequest{}, err\n\t}\n\tttd := t.At(0)\n\tif err := BuildInto(&ttd, tenant, tsreq, builder); err != nil {\n\t\treturn WriteRequest{}, err\n\t}\n\tif err := marshalSymbols(builder, sym); err != nil {\n\t\treturn WriteRequest{}, err\n\t}\n\treturn wr, nil\n}\n\nfunc BuildInto(wr *TimeSeriesTenantTuple, tenant string, tsreq []prompb.TimeSeries, builder *symboltable.Builder) error {\n\tif err := wr.SetTenant(tenant); err != nil {\n\t\treturn errors.Wrap(err, \"set tenant\")\n\t}\n\n\tseries, err := wr.NewTimeSeries(int32(len(tsreq)))\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor i, ts := range tsreq {\n\t\ttsc := series.At(i)\n\n\t\tlblsc, err := tsc.NewLabels(int32(len(ts.Labels)))\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"new labels\")\n\t\t}\n\t\tif err := marshalLabels(lblsc, ts.Labels, builder); err != nil {\n\t\t\treturn errors.Wrap(err, \"marshal labels\")\n\t\t}\n\t\tif err := marshalSamples(tsc, ts.Samples); err != nil {\n\t\t\treturn errors.Wrap(err, \"marshal samples\")","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/receive/writecapnp/marshal.go#L51-L87","documentation":"BuildInto serializes a multi-tenant WriteRequest into a capnp message. The first step, wr.SetTenant(tenant), sets the tenant string field on the TimeSeriesTenantTuple; if the capnp arena cannot allocate or write the string, the error is wrapped with 'set tenant'.","triggerScenarios":"SetTenant fails on the capnp struct — typically message/arena allocation failure because the buffer is exhausted, or (depending on the capnp binding) an invalid/oversized tenant string.","commonSituations":"Very large batched writes exhausting the capnp segment size limit; a tenant id that is empty or abnormally large; running against a capnp version where string setters allocate eagerly.","solutions":["Reduce the batch size of tsreq passed to BuildInto","Validate tenant is non-empty and of sane length before calling BuildInto","Increase the capnp message buffer/arena size if configured","Check the underlying capnp library version for known allocation limits","If persistent, fall back to BuildIntoSingleTenantWriteRequest per-tenant batches"],"exampleFix":"// before\nerr := BuildInto(tuple, tenant, tsreq, builder)\n// after\nif tenant == \"\" || len(tenant) > 255 {\n    return fmt.Errorf(\"invalid tenant %q\", tenant)\n}\nerr := BuildInto(tuple, tenant, tsreq, builder)","handlingStrategy":"validation","validationCode":"func validateTenant(t string) error {\n    if t == \"\" { return errors.New(\"tenant must not be empty\") }\n    if len(t) > 255 { return errors.New(\"tenant too long\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := BuildInto(tuple, tenant, tsreq, builder); err != nil && strings.Contains(err.Error(), \"set tenant\") {\n    // tenant field write failed: fall back to smaller batch or per-tenant split\n    return handleMarshalFailure(err, tenant, tsreq)\n}","preventionTips":["Validate tenant ids at ingestion boundaries","Keep batch sizes bounded","Pin and test capnp dependency versions"],"tags":["capnp","serialization","allocation"],"backgroundTag":"schema-validation-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}