{"id":"e2b80118dbda184e","repo":"jackc/pgx","slug":"failed-to-write-to-large-object","errorCode":null,"errorMessage":"failed to write to large object","messagePattern":"failed to write to large object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"large_objects.go","lineNumber":94,"sourceCode":"// Write writes p to the large object and returns the number of bytes written and an error if not all of p was written.\nfunc (o *LargeObject) Write(p []byte) (int, error) {\n\tnTotal := 0\n\tfor {\n\t\texpected := len(p) - nTotal\n\t\tif expected == 0 {\n\t\t\tbreak\n\t\t} else if expected > maxLargeObjectMessageLength {\n\t\t\texpected = maxLargeObjectMessageLength\n\t\t}\n\n\t\tvar n int\n\t\terr := o.tx.QueryRow(o.ctx, \"select lowrite($1, $2)\", o.fd, p[nTotal:nTotal+expected]).Scan(&n)\n\t\tif err != nil {\n\t\t\treturn nTotal, err\n\t\t}\n\n\t\tif n < 0 {\n\t\t\treturn nTotal, errors.New(\"failed to write to large object\")\n\t\t}\n\n\t\tnTotal += n\n\n\t\tif n < expected {\n\t\t\treturn nTotal, errors.New(\"short write to large object\")\n\t\t} else if n > expected {\n\t\t\treturn nTotal, errors.New(\"invalid write to large object\")\n\t\t}\n\t}\n\n\treturn nTotal, nil\n}\n\n// Read reads up to len(p) bytes into p returning the number of bytes read.\nfunc (o *LargeObject) Read(p []byte) (int, error) {\n\tnTotal := 0\n\tfor {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/large_objects.go#L76-L112","documentation":"Returned by LargeObject.Write when SELECT lowrite($1,$2) scanned a byte count n < 0 (large_objects.go:93-95). The lowrite server function returns -1 (and raises an exception) on internal failure; pgx surfaces the negative count as this error, meaning the server rejected the write (e.g. the descriptor is invalid, the large object was not opened for writing, or the descriptor's transaction ended).","triggerScenarios":"Calling Write on a LargeObject whose fd is stale: opened in LargeObjectModeRead instead of Write, already Closed, or used after its creating transaction committed/rolled back (large objects are only valid within their creating transaction).","commonSituations":"Forgetting LargeObjectModeWrite when opening; writing after Close(); writing across a transaction boundary (the fd is invalid once the transaction ends); using a LargeObject from a different transaction.","solutions":["Open the large object with LargeObjectModeWrite (bit 0x20000) before calling Write.","Keep all Write/Read/Seek/Close calls within the same transaction that called LargeObjects.Open; commit/rollback invalidates the fd.","Do not call Close() before Write(); structure the lifecycle: Open → Write → Close within one tx.","Use Tx.LargeObjects() to obtain the LargeObjects handle tied to the active transaction."],"exampleFix":"// before\nlo, _ := los.Open(ctx, oid, pgx.LargeObjectModeRead) // wrong mode\n_, err := lo.Write(data) // \"failed to write to large object\"\n\n// after\nlo, err := los.Open(ctx, oid, pgx.LargeObjectModeWrite)\nif err != nil { return err }\nif _, err := lo.Write(data); err != nil { return err }\nreturn lo.Close()","handlingStrategy":"try-catch","validationCode":"// open with Write mode and verify fd >= 0 before writing\nlo, err := los.Open(ctx, oid, pgx.LargeObjectModeWrite)\nif err != nil { return err }\n// keep within the same transaction","typeGuard":"func openForWrite(m pgx.LargeObjectMode) bool {\n    return m&pgx.LargeObjectModeWrite != 0\n}","tryCatchPattern":"if _, err := lo.Write(p); err != nil {\n    if err.Error() == \"failed to write to large object\" {\n        // re-open in Write mode within a live transaction, then retry\n    }\n    return err\n}","preventionTips":["Always open with LargeObjectModeWrite before writing.","Keep Write/Close within the same transaction that opened the LO.","Never reuse a LargeObject after its transaction ends."],"tags":["large-objects","write","transaction","file-descriptor"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}