Package · sdk-s5w

Exceptions

Everything the SDK throws extends S5wException. The exception’s class says what happened; the message text is meant for logs. Handling them in practice — in the Error handling guide.

Root Flytachi\Winter\SDK\S5w\S5wExceptionThe rest Flytachi\Winter\SDK\S5w\Exception

Hierarchy

text
S5wException                         RuntimeException; the root of every SDK error
├── TransportException                the server did not answer: DNS, refused connection, timeout
├── ResponseException                 an answer came, but not in S5W's format
├── ApiException                      the server answered with an error status
│   ├── UnauthorizedException   401   no key, or the server does not know it
│   ├── ForbiddenException      403   the key is disabled, expired, or BASIC where FULL is needed
│   ├── NotFoundException       404   no such file, folder or session
│   ├── ConflictException       409   the name is taken; a chunk does not continue the upload
│   ├── PayloadTooLargeException 413  the quota is full; a chunk is too large
│   ├── ValidationException     422   the parameters failed validation
│   └── ServerException         5xx   a failure on the server's side
├── UploadInterruptedException        a chunked upload stopped, the session can be continued
└── UploadUnconfirmedException        assembling the file was requested but not confirmed

S5wException

The root of the hierarchy, a subclass of RuntimeException. Catch it and you catch any SDK error.

It is also thrown directly — for errors the SDK finds before any request: invalid configuration, a file that cannot be read from disk, a file that changed during the upload, a file whose size does not match the session on resume().

Message

Messages look like S5W {path}: {status} {server text}:

text
S5W v1/files/7CKEKbaV8AN6qTs1: 404 File does not exist
S5W v1/folders: 409 Folder "avatars" already exists
S5W v1/files: 422 Folder "no-such" does not exist
S5W v1/check: simulated: connection refused

The path is shown decoded — non-Latin folder names read as they are.

ApiException

The server answered with an error status. The body is { code, message, errors? }. For the statuses in the table below a subclass is thrown; for the others (400, for example) — ApiException itself.

Status Class Typical causes
400 ApiException an empty chunk, or a chunk under 4 MiB that is not the last
401 UnauthorizedException no key, or an unknown one
403 ForbiddenException the key is disabled or expired; a BASIC key for folders(), files(), uploads()
404 NotFoundException no such file, folder, session; a malformed file id (no request)
409 ConflictException a folder or file name is taken; the chunk offset does not match; complete() before every byte arrived
413 PayloadTooLargeException the bucket’s quota is full; a chunk over 16 MiB or past the declared size
422 ValidationException a field failed validation; no such folder; image options for a non-image; a hash mismatch
5xx ServerException a server error; 507 — the server’s disk has no room

Methods

status(): int — the HTTP status of the answer.

errors(): array<string, list<string>> — per-field errors; filled only for a 422 with field validation errors.

method(): string — the request’s HTTP method, e.g. "PUT".

path(): string — the request path relative to the server address, e.g. "v1/files/7CKEKbaV8AN6qTs1".

php
catch (ApiException $e) {
  $e->status();   // 409
  $e->method();   // "POST"
  $e->path();     // "v1/folders"
}

ValidationException

An extra method, errorsOf(string $field): list<string> — the errors of one field.

php
catch (ValidationException $e) {
  $e->errors();          // ["name" => ["must not be blank", "size must be between 1 and 100"]]
  $e->errorsOf('name');  // ["must not be blank", "size must be between 1 and 100"]
  $e->errorsOf('other'); // []
}

If the error is about the whole request rather than a field (no such folder, a hash mismatch), errors() is empty and the cause is in the message.

TransportException

The request got no HTTP answer: the server was not found, the connection was refused, the timeout expired. The one kind of failure worth retrying as it is.

Methods

isTimeout(): bool — true if the cause is an expired timeout rather than a refused connection.

The HTTP client’s original exception is available through getPrevious().

ResponseException

An answer came, but it is not an S5W answer: not JSON, a field missing, a field of the wrong type. Usually the address points at something other than S5W (a proxy error page, say), or the server and SDK versions disagree. The message names the field:

text
S5W v1/check: the answer is not JSON
S5W v1/check: bytes.quota must be int, got string

UploadInterruptedException

A chunked upload stopped on a network or server failure after every attempt (Uploads::ATTEMPTS) ran out. The session is kept on the server — it can be continued within 24 hours of the last chunk received.

Thrown by uploads()->send(), sendContent(), resume(), and by files()->upload() and uploadContent() for files over the chunked-upload threshold.

Methods

sessionId(): string — the session id; pass it to uploads()->resume().

offset(): int — how many bytes, as far as the SDK knows, are already on the server.

size(): int — the full file size.

The cause is in getPrevious(): TransportException, ServerException or ConflictException.

php
catch (UploadInterruptedException $e) {
  $file = $s5w->uploads()->resume($e->sessionId(), $path);
}

UploadUnconfirmedException

Every byte was sent and assembling the file was requested, but no answer came (a broken connection, a gateway error), and the session is no longer on the server. The file may have been created — then its id is unknown; or it may not. The SDK does not try to guess: a name search could find someone else’s file.

Methods

sessionId(): string — the id of the session that is gone.

name(): string — the name the upload started with. The stored name may differ — e.g. name (1).ext if the name was taken.

php
catch (UploadUnconfirmedException $e) {
  $logger->error("Upload of {$e->name()} not confirmed — check the folder by hand");
}

What methods throw

Method Characteristic exceptions
S5w::check() UnauthorizedException, ForbiddenException
Folders::create(), rename(), update() ConflictException, ValidationException, NotFoundException
Folders::get(), delete() NotFoundException
Files::get(), delete() NotFoundException
Files::list() ValidationException (no such folder)
Files::rename(), move(), update() NotFoundException, ValidationException, ConflictException
Files::upload(), uploadContent() ValidationException, PayloadTooLargeException; for large files — as send()
Uploads::start() ValidationException, PayloadTooLargeException, ServerException (507)
Uploads::append() ConflictException, PayloadTooLargeException, ApiException (400), NotFoundException
Uploads::complete() ConflictException, ValidationException
Uploads::send(), sendContent() UploadInterruptedException, UploadUnconfirmedException, ApiException
Uploads::resume() as send(), plus NotFoundException and S5wException (a different file)

Any method that talks to the server may also throw TransportException, ResponseException, UnauthorizedException and ForbiddenException.