apache/hadoop · error · IOException
write has error. bs : pre upload obs[%s] has error.
Error message
write has error. bs : pre upload obs[%s] has error.
What it means
OBSBlockOutputStream.write() checks the hasException AtomicBoolean: once any earlier block upload or internal operation failed, every subsequent write() fails fast with IOException('write has error. bs : pre upload obs[<key>] has error.'). This is a secondary, deliberately uninformative error — the real failure was logged when hasException was set. Its purpose is to stop the write path from piling more data onto a stream that is already known-broken.
Source
Thrown at hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSBlockOutputStream.java:307
/**
* Writes a range of bytes from to the memory buffer. If this causes the
* buffer to reach its limit, the actual upload is submitted to the threadpool
* and the remainder of the array is written to memory (recursively).
*
* @param source byte array containing
* @param offset offset in array where to start
* @param len number of bytes to be written
* @throws IOException on any problem
*/
@Override
public synchronized void write(@NotNull final byte[] source,
final int offset, final int len)
throws IOException {
if (hasException.get()) {
String closeWarning = String.format(
"write has error. bs : pre upload obs[%s] has error.", key);
LOG.warn(closeWarning);
throw new IOException(closeWarning);
}
OBSDataBlocks.validateWriteArgs(source, offset, len);
checkOpen();
if (len == 0) {
return;
}
OBSDataBlocks.DataBlock block = createBlockIfNeeded();
int written = block.write(source, offset, len);
int remainingCapacity = block.remainingCapacity();
try {
innerWrite(source, offset, len, written, remainingCapacity);
} catch (IOException e) {
LOG.error(
"Write data for key {} of bucket {} error, error message {}",
key, fs.getBucket(),
e.getMessage());
throw e;View on GitHub (pinned to 2add963021)
Solutions
- Scroll UP in the logs to the first exception for this key — that root cause (auth, network, quota) is what to fix; this exception is only the messenger.
- Close/abort the stream and fail the task; then retry the whole write from the last committed point (multipart parts already uploaded are discarded on abort).
- If root cause is transient (5xx, connection reset), enable/verify fs.obs.attempts and retry policy on the client and retry the job.
- If root cause is credentials, refresh AK/SK or session token before the retry; expired temporary credentials are the most common cause in long jobs.
Example fix
// before
try { out.write(buf, 0, n); } catch (IOException e) { log.warn("write failed, keep going"); }
out.write(more); // -> 'pre upload obs[...] has error'
// after
try {
out.write(buf, 0, n);
} catch (IOException e) {
quietlyAbort(out); // ((OBSBlockOutputStream) out.getWrappedStream()).abort() or close quietly
throw new RuntimeException("OBS write failed for " + path, e); // fail task, retry job
} Defensive patterns
Strategy: try-catch
Validate before calling
// no public isFailed() exists; track the first failure in your wrapper
class SafeObsWriter {
private volatile boolean failed;
void write(FSDataOutputStream out, byte[] b, int off, int len) throws IOException {
if (failed) throw new IllegalStateException("stream already failed");
try { out.write(b, off, len); }
catch (IOException e) { failed = true; throw e; }
}
} Try / catch
try {
out.write(buf, 0, n);
} catch (IOException e) {
if (String.valueOf(e.getMessage()).contains("pre upload obs[")) {
abortQuietly(out);
throw new RuntimeException("OBS stream poisoned by earlier failure — see first exception in logs", e);
}
throw e;
} Prevention
- Never catch-and-continue around write(); fail the task on the FIRST exception.
- Rotate temporary credentials before expiry in long jobs.
- Alert on the first upload failure, not on the cascade of 'pre upload obs[...] has error' messages.
- Wrap streams in a failing-fast proxy that remembers the first error.
When it happens
Trigger: A background block upload (multipart part) failed earlier — network reset, 401/403 expired credentials, 5xx from OBS, out-of-memory in the buffering block factory — and the caller ignores the first exception and keeps writing; async failure happens between two write() calls, so the next write() sees hasException==true; previous flush() swallowed an exception in an outer wrapper.
Common situations: Long-running Spark/Hive writes where a transient network blip failed one part upload; AK/SK revocation mid-job; executors with tight memory causing block allocation failures; callers that catch-and-continue around write loops.
Related errors
- flushOrSync has error. bs : pre write obs[%s] has error.
- Proxy error: %s or %s set without the other.
- From option %s %s
- Filesystem %s closed
- closed has error. bs : pre write obs[%s] has error.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d3dbc2954aaf8690.
Report an issue: GitHub.