Skip to content

Manual import to CIFS root ignores explicit case-sensitivity setting and fails in ManualImportDestinationTracker #820

Description

@Art3misFoul

Manual import to CIFS root ignores explicit case-sensitivity setting and fails in ManualImportDestinationTracker

Summary

Manual import fails when the destination root is a CIFS/SMB filesystem, even though the Listenarr root is explicitly configured as Insensitive and the persisted resolved case sensitivity is also Insensitive.

The failure occurs in ManualImportDestinationTracker.PlanAsync() while planning the destination:

The filesystem does not expose read-only case-sensitivity metadata. Select Sensitive or Insensitive explicitly.

A native-storage control test using the same audiobook, same Docker container, same import workflow, and Move action succeeds. Changing only the destination to the CIFS root reproduces the failure.

This appears to be a regression or edge case in the filesystem semantics changes introduced in Listenarr 1.3.0 / PR #717.

Environment

  • Listenarr: 1.3.0-canary
  • Image: ghcr.io/listenarrs/listenarr:canary
  • Running image ID: sha256:f3a0cacad57c0a7d4f7ba43189920e06999e526bb7cb165891e46241788371cf
  • Image created: 2026-08-12T14:27:26.087423457Z
  • GHCR digest: sha256:734941169e4ebb5b9fd1ee5e6d99d904cd687eaa79803535c00c7d0302703430
  • Host: Unraid
  • Kernel: 6.18.33-Unraid
  • Docker container is running as root for troubleshooting, so this does not appear to be a Unix permissions problem.

CIFS storage configuration

Docker mapping:

/mnt/remotes/10.0.10.3_Media/Audiobooks -> /audiobooks (rw)

Host filesystem:

TARGET:  /mnt/remotes/10.0.10.3_Media
SOURCE:  //10.0.10.3/Media
FSTYPE:  cifs
OPTIONS: rw,relatime,vers=3.1.1,cache=strict,...,uid=99,forceuid,gid=100,forcegid,
         file_mode=0777,dir_mode=0777,iocharset=utf8,hard,nounix,mapposix,...

Inside the container:

smb2 /audiobooks

The filesystem is actually case-insensitive:

touch "$testdir/CaseProbe"

[ -e "$testdir/caseprobe" ]
# true

Result:

CASE=INSENSITIVE

The CIFS filesystem also exposes inode and birth-time information, for example:

dev=55 inode=2417 birth=1702039280 type=directory path=/audiobooks

Listenarr root state

The /audiobooks root is explicitly configured as case-insensitive, not Auto.

Persisted RootFolders state:

Name:                    Default
Path:                    /audiobooks
CaseSensitivityMode:     Insensitive
ResolvedCaseSensitivity: Insensitive
PathIdentityState:       Valid
DirectoryObjectIdentity: populated
DirectoryObjectIdentityVersion: 1
DirectoryObjectIdentityUnavailableReason: empty

So the root configuration and actual filesystem behavior agree that this root is case-insensitive.

Steps to reproduce

I used a second temporary root backed by local/native Unraid storage:

/native-test
CaseSensitivityMode:     Sensitive
ResolvedCaseSensitivity: Sensitive
PathIdentityState:       Valid

Test audiobook:

/native-test/14 [B0089Y7K0M]/14.m4b
  1. Scan /native-test using Library Import.
  2. Match the M4B to audiobook ASIN B0089Y7K0M.
  3. Set the import action to Move.
  4. Set /audiobooks (CIFS) as the default/destination root.
  5. Start the import.

The source is definitely native storage and the destination is definitely CIFS. After the failure, the audiobook record contains:

BasePath: /audiobooks
FilePath: NULL

No AudiobookFiles row is created.

Actual behavior

Metadata lookup and ffprobe succeed.

Immediately afterward, destination planning fails:

[ERR] [Listenarr.Api.Features.Downloads.ManualImportController]
Error importing file /native-test/14 [B0089Y7K0M]/14.m4b

System.InvalidOperationException:
The filesystem does not expose read-only case-sensitivity metadata.
Select Sensitive or Insensitive explicitly.

   at Listenarr.Api.Features.Downloads.ManualImportDestinationTracker.PlanAsync(
       String sourcePath,
       String desiredDestination,
       Boolean allowExistingEquivalent,
       CancellationToken cancellationToken)
   in .../ManualImportDestinationTracker.cs:line 71

   at Listenarr.Api.Features.Downloads.ManualImportController.ImportFileAsync(...)
   in .../ManualImportController.ProcessItem.cs:line 133

The batch then finishes:

Manual import companion-file pass completed with 0 imported companion file(s)
Manual import batch completed: 0/1 succeeded, usedDestinations: 0

Expected behavior

Because /audiobooks is a configured Listenarr root with:

CaseSensitivityMode = Insensitive
ResolvedCaseSensitivity = Insensitive
PathIdentityState = Valid

I would expect destination planning to use those explicit configured filesystem semantics rather than requiring the CIFS filesystem to expose additional read-only case-sensitivity metadata.

The import should proceed using case-insensitive path semantics.

Native-storage control test

The same audiobook and Move workflow succeeds when both source and destination use the native /native-test root.

Successful log sequence:

Created AudiobookFile for audiobook 146: 14.m4b Id=1

File mutation Success: Move 14.m4b -> 14.m4b

Manual import batch completed: 1/1 succeeded, usedDestinations: 1

Enqueued focused scan ... for audiobook 146

Scan job ... status to Completed

The resulting file record is valid and contains a physical identity:

PathCaseSensitivity:     Sensitive
PathCaseSensitivityMode: Sensitive
PathIdentityState:       Valid
PhysicalObjectIdentity:  populated

Therefore:

native source -> native destination = succeeds
native source -> CIFS destination   = fails

This isolates the failure to destination handling for the CIFS root rather than metadata matching, ffprobe, the source file, the audiobook, Docker permissions, or the general manual-import workflow.

Additional observation

An SMB-source import also fails earlier with the same underlying exception:

System.InvalidOperationException:
The filesystem does not expose read-only case-sensitivity metadata.
Select Sensitive or Insensitive explicitly.

at ManualImportController.ResolvePathSemanticsAsync(...)
    ManualImportController.PathSemantics.cs:line 113

So CIFS appears to affect both source and destination semantics resolution.

Possibly related scan behavior

The same CIFS root can be enumerated normally; an unmatched scan of /audiobooks successfully discovers 164 items.

However, focused scans of library entries under that root can also be rejected with:

Rejected scan path for audiobook ...:
The configured scan root no longer identifies its enrolled physical generation.

The UI returns:

{
  "message": "Scan path identity could not be established safely",
  "reason": "IdentityUnavailable"
}

The configured root itself remains:

PathIdentityState = Valid
DirectoryObjectIdentityUnavailableReason = empty

This may be related to the same CIFS/filesystem-identity handling introduced in 1.3.0, but I can open it as a separate issue if preferred.

Notes

  • Re-saving/re-enrolling the CIFS root does not fix the problem.
  • Restarting the container does not fix it.
  • The running :canary image was verified against GHCR and is current.
  • Both Docker mounts are read/write.
  • The problem is reproducible with a single M4B.
  • No manual SQLite modifications have been made.
  • The CIFS root's explicit Insensitive setting matches an independent filesystem case-sensitivity test.
  • A native-to-native import succeeds under the same container and workflow.
  • I can provide additional debug logs, database schema/state, or run further filesystem tests if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions