nextcloud/server · error · Sabre\DAV\Exception\ServiceUnavailable
File is not updatable: %1$s
Error message
File is not updatable: %1$s
What it means
At the start of PUT, file_exists() on the file's view raised StorageNotAvailableException — the backend holding the file (external storage: SMB, SFTP, S3, ...) is unavailable. It is wrapped as ServiceUnavailable (HTTP 503) with the message 'File is not updatable: <backend message>'. Despite the wording, this signals storage unavailability, not a permission problem.
Source
Thrown at apps/dav/lib/Connector/Sabre/File.php:122
*
* @throws Forbidden
* @throws UnsupportedMediaType
* @throws BadRequest
* @throws Exception
* @throws EntityTooLarge
* @throws ServiceUnavailable
* @throws FileLocked
* @return string|null
*/
#[\Override]
public function put($data) {
try {
$exists = $this->fileView->file_exists($this->path);
if ($exists && !$this->info->isUpdateable()) {
throw new Forbidden();
}
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable($this->l10n->t('File is not updatable: %1$s', [$e->getMessage()]));
}
// verify path of the target
$this->verifyPath();
[$partStorage] = $this->fileView->resolvePath($this->path);
if ($partStorage === null) {
throw new ServiceUnavailable($this->l10n->t('Failed to get storage for file'));
}
$needsPartFile = $partStorage->needsPartFile() && (strlen($this->path) > 1);
$view = Filesystem::getView();
if ($needsPartFile) {
$transferId = \rand();
// mark file as partial while uploading (ignored by the scanner)
$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . $transferId . '.part';
View on GitHub (pinned to ecdeb153ff)
Solutions
- Check the external storage entry in the admin UI (it reports availability) and nextcloud.log for the underlying storage exception.
- Repair the backend: restore the server, update credentials, fix mount options.
- Retry the PUT once the storage is healthy; clients should treat 503 as retryable with backoff.
Defensive patterns
Strategy: try-catch
Try / catch
try {
$client->request('PUT', $fileUrl, $content);
} catch (ServiceUnavailable $e) { // 503 'File is not updatable: ...'
// backend storage down — keep the content and retry later
queueForRetryWithBackoff($fileUrl, $content);
} Prevention
- Monitor external storage availability; a 503 on PUT usually means the backend is down.
- Rotate storage credentials on both sides simultaneously to avoid auth gaps.
- Make uploads idempotent and retryable with backoff on 503.
When it happens
Trigger: PUT to a file on an external storage that is offline, has expired credentials, or exceeds backend timeouts; misconfigured mounts whose storage cannot even stat the path.
Common situations: SMB server down; SFTP credential or host-key rotation breaking auth; S3 signature errors after key changes; slow mounts tripping availability checks.
Related errors
- No read permissions
- Entity does not exist or is not available
- $class: $msg
- No read permissions. This might be caused by files_accesscon
- filesystem not setup
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/e4a69a8b1ca71e9c.
Report an issue: GitHub.