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

  1. Check the external storage entry in the admin UI (it reports availability) and nextcloud.log for the underlying storage exception.
  2. Repair the backend: restore the server, update credentials, fix mount options.
  3. 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

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


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/e4a69a8b1ca71e9c. Report an issue: GitHub.