fix(upload): plain-language upload failure text instead of the raw MatrixError (#213)
The upload card printed the SDK's toString — 'MatrixError: [413] nope (http://<hs>/_matrix/media/v3/upload?filename=…)'. describeUploadError() maps the common cases to one sentence: 413/M_TOO_LARGE → 'This file is larger than the server allows (limit N)' using m.upload.size when known, 429 → 'Slow down — try again in a moment.', 401/403 → 'The server refused this upload: <server text>', 5xx/transport after the retry loop → 'Couldn't reach the server. Check your connection and retry.', other 4xx → the server's own sentence, URL stripped. Both card renderers use it; the raw error is still console.warn-ed by uploadContent for debugging. Unit-tested; verified headless with routed 413/403/503 responses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
+11
-5
@@ -221,12 +221,18 @@ export const uploadContent = async (
|
||||
|
||||
const abortError = () =>
|
||||
matrixErrorFromUnknown(new DOMException('Upload cancelled', 'AbortError'));
|
||||
// The card shows a plain sentence (describeUploadError); keep the raw error
|
||||
// (status, errcode, URL) in the console for debugging.
|
||||
const fail = (err: MatrixError) => {
|
||||
if (err.data?.error !== 'Upload cancelled') console.warn('[upload] failed:', err);
|
||||
onError(err);
|
||||
};
|
||||
|
||||
let lastError: MatrixError | undefined;
|
||||
|
||||
for (let retryCount = 0; retryCount <= UPLOAD_MAX_RETRY_COUNT; retryCount += 1) {
|
||||
if (signal?.aborted) {
|
||||
onError(abortError());
|
||||
fail(abortError());
|
||||
return;
|
||||
}
|
||||
const uploadPromise = mx.uploadContent(file, {
|
||||
@@ -246,13 +252,13 @@ export const uploadContent = async (
|
||||
return;
|
||||
}
|
||||
// Missing content_uri is not a transient failure — fail immediately.
|
||||
onError(matrixErrorFromUploadResponse(data));
|
||||
fail(matrixErrorFromUploadResponse(data));
|
||||
return;
|
||||
} catch (e: unknown) {
|
||||
lastError = matrixErrorFromUnknown(e);
|
||||
|
||||
if (retryCount === UPLOAD_MAX_RETRY_COUNT || !isRetryableUploadError(e, !!signal?.aborted)) {
|
||||
onError(lastError);
|
||||
fail(lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -265,14 +271,14 @@ export const uploadContent = async (
|
||||
await sleepForMs(waitMS);
|
||||
// Cancelled during the back-off — stop instead of resurrecting the upload.
|
||||
if (signal?.aborted) {
|
||||
onError(abortError());
|
||||
fail(abortError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unreachable in practice, but keeps onError guaranteed if the loop exits.
|
||||
if (lastError) onError(lastError);
|
||||
if (lastError) fail(lastError);
|
||||
};
|
||||
|
||||
export const matrixEventByRecency = (m1: MatrixEvent, m2: MatrixEvent) => m2.getTs() - m1.getTs();
|
||||
|
||||
Reference in New Issue
Block a user