AlistGo/alist · error

failed to convert path to remote path: %w

Error message

failed to convert path to remote path: %w

What it means

Thrown by Crypt.Link when translating the user-visible (decrypted) file path to the remote storage's internal actual path fails. getActualPathForRemote encrypts the directory/file names, joins them onto RemotePath, then calls op.GetStorageAndActualPath to split the result into storage + actual path. Any failure there — most commonly the storage mount no longer resolving — surfaces wrapped in this message, aborting the link/download operation before the remote link is even requested.

Source

Thrown at drivers/crypt/driver.go:247

			log.Warnf("DecryptDirName failed for %s ,will use original name, err:%s", path, err)
			name = remoteObj.GetName()
		}
	}
	obj := &model.Object{
		Path:     path,
		Name:     name,
		Size:     size,
		Modified: remoteObj.ModTime(),
		IsFolder: remoteObj.IsDir(),
	}
	return obj, nil
	//return nil, errs.ObjectNotFound
}

func (d *Crypt) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
	dstDirActualPath, err := d.getActualPathForRemote(file.GetPath(), false)
	if err != nil {
		return nil, fmt.Errorf("failed to convert path to remote path: %w", err)
	}
	remoteLink, remoteFile, err := op.Link(ctx, d.remoteStorage, dstDirActualPath, args)
	if err != nil {
		return nil, err
	}

	if remoteLink.RangeReadCloser == nil && remoteLink.MFile == nil && len(remoteLink.URL) == 0 {
		return nil, fmt.Errorf("the remote storage driver need to be enhanced to support encrytion")
	}
	remoteFileSize := remoteFile.GetSize()
	remoteClosers := utils.EmptyClosers()
	rangeReaderFunc := func(ctx context.Context, underlyingOffset, underlyingLength int64) (io.ReadCloser, error) {
		length := underlyingLength
		if underlyingLength >= 0 && underlyingOffset+underlyingLength >= remoteFileSize {
			length = -1
		}
		rrc := remoteLink.RangeReadCloser
		if len(remoteLink.URL) > 0 {

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Confirm the underlying storage still exists and is mounted at the path RemotePath points to; re-add or fix it if missing
  2. Refresh/re-save the crypt storage so Init re-resolves d.remoteStorage against current mounts
  3. Check logs for the wrapped op.GetStorageAndActualPath error to identify whether the storage root or the sub-path failed
  4. Avoid renaming the underlying storage's mount path; if renamed, update RemotePath accordingly
Defensive patterns

Strategy: validation

Validate before calling

// Before requesting a link, confirm the crypt storage's remote still resolves
if _, _, err := op.GetStorageAndActualPath(remotePathOfCryptStorage); err != nil {
    return fmt.Errorf("underlying storage unavailable: %w", err)
}

Try / catch

link, err := cryptDriver.Link(ctx, file, args)
if err != nil {
    if strings.Contains(err.Error(), "failed to convert path to remote path") {
        // storage-mount drift: surface a config error, don't retry the download
        return nil, fmt.Errorf("crypt remote storage misconfigured: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Requesting a download link (Link) for a file inside the crypt mount when the underlying remote storage has been unmounted/deleted/renamed since the crypt storage was initialized, or when the encrypted path fails to map under the mounted storage path (RemotePath drift, cached stale storage reference after restart).

Common situations: Underlying storage removed while crypt storage still references it; AList restart where d.remoteStorage holds a stale mount; RemotePath pointing at a subfolder that was moved on the remote; path containing characters that after encryption break the storage-path split.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/da1c34c62f98a134. Report an issue: GitHub.