Skip to content

A freshly formatted SD card will show "SD CARD ERROR" once firmware stops auto-creating the log directory #827

Description

@cptkoolbeenz

What will break

SdCardFailureClassifier.Classify is a C# switch expression, so its type patterns are tested in order. Daqifi.Core now throws SdCardDirectoryNotFoundException, which derives from SdCardFilesystemException — so it falls into this arm (SdCardFailureClassifier.cs:189):

SdCardFilesystemException filesystem => new SdCardFailure(
    State: SdCardState.Error,
    StatusMessage: filesystem.DeviceMessage ?? filesystem.Message,
    Guidance: GENERIC_CARD_GUIDANCE,
    ...

Result: the user formats a card, opens the SD panel, and gets the red SD CARD ERROR panel reading [Error:5]Failed to open directory [DAQiFi] — for a card that is perfectly healthy and simply has nothing logged to it yet.

This file already knows about this hazard; the SdCardTransferStalledException arm carries the comment "It must precede the SdCardOperationException arm below, which is its base type." The same ordering rule applies here and is not yet satisfied.

Why it is not broken today

Current firmware silently creates the directory during a read-only SYST:STOR:SD:LISt? and then reports it empty, so the condition never arises. daqifi-nyquist-firmware#798 stops that — a query must not modify the card — which makes "that directory is not on the card" observable for the first time.

So this is a latent break, armed by a firmware PR that has not merged yet.

The fix

Add an arm before the SdCardFilesystemException one, mapping it to the ordinary empty-card state rather than an error:

// Not a fault: a freshly formatted card has no log directory until the first capture
// writes one. MUST precede the SdCardFilesystemException arm below, which is its base type.
SdCardDirectoryNotFoundException => new SdCardFailure(
    State: SdCardState.Ok,
    StatusMessage: string.Empty,
    Guidance: NO_LOGS_YET_GUIDANCE,
    IsExpectedDeviceCondition: true,
    IsCardUnavailable: false),

SdCardState.Ok is the right target, and the existing view logic already does the rest:

  • HasSdCardError => CanAccessSdCard && SdCardState == SdCardState.Error → the red panel stays hidden.
  • HasNoFiles => (DeviceFiles?.Any() != true) && CanAccessSdCard && SdCardState == SdCardState.Ok → the normal empty state shows instead.
  • SdCardStatusLine renders · SD card OK · 0 files.

LogFailure keeps it at Warning (no Sentry) because IsExpectedDeviceCondition: true.

Blocked on a Daqifi.Core release — this is the actual gate

Daqifi.Desktop.csproj:41 pins Daqifi.Core 1.4.0. The type landed in daqifi-core#551, which merged to main on 2026-08-19 — after the newest release, v1.6.0 (2026-08-16). It is therefore in no published package, and the code above will not compile until:

  1. a Daqifi.Core release ships containing deps: align NuGet package versions (supersedes #533, #536, #539) #551 (v1.7.0 or later), then
  2. this repo bumps its Daqifi.Core reference (1.4.0 → that release), then
  3. the classifier arm + a test land.

Worth noting the pin is already two releases behind (1.4.0 vs 1.6.0), so step 2 is a bump worth reviewing on its own merits rather than a one-line version edit.

Ordering

Firmware #798 should not merge before this is in a shipped desktop build, or users on new firmware see the error panel on every freshly formatted card. That ordering is already called out on the firmware PR — this issue is the desktop half of it.

Test

Mirror Classify_FilesystemError_SurfacesTheDeviceMessageAndKeepsTheRestOfTheCardUsable in Daqifi.Desktop.Test/ViewModels/SdCardFailureClassifierTests.cs, asserting SdCardState.Ok and IsCardUnavailable: false. Make it construct a real SdCardDirectoryNotFoundException rather than a mock, so it genuinely pins the subclass-before-base ordering — a test against the base type alone would pass with the bug present.

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