Blog

OSLog Logger Crashes SwiftUI Previews: Fix for 'argument must be a string interpolation'

Published on Feb 7, 2026

If your SwiftUI preview is crashing with the error "argument must be a string interpolation" and you're using OSLog.Logger, you're hitting a known conflict between Xcode's preview compiler and OSLog's special string handling.

The error

You'll see something like this in the preview diagnostics:

Compiling failed: argument must be a string interpolation
 
logger.debug(__designTimeString("#24265_0", fallback: "Some log message"))
                                 `- error: argument must be a string interpolation

The key clue is __designTimeString -- you didn't write that. Xcode injected it.

Why this happens

There are two systems fighting each other:

OSLog requires string interpolation. Unlike a normal function that accepts a String, Logger.debug, Logger.info, Logger.error, etc. require a special OSLogInterpolation type. The Swift compiler creates this type automatically when you use string interpolation \() directly inside the logger call. This is how OSLog enforces privacy and performance at compile time. Plain string literals work too, because the compiler implicitly wraps them.

Xcode previews replace string literals. When building for previews, Xcode's compiler injects a function called __designTimeString around every string literal. This is what enables live editing of strings in the preview canvas.

So your code:

logger.debug("User completed onboarding")

Becomes this during the preview build:

logger.debug(__designTimeString("#12345_0", fallback: "User completed onboarding"))

The __designTimeString function returns a regular String, not the OSLogInterpolation that Logger.debug expects. Type mismatch. Compilation fails. Preview crashes.

The fix

Wrap the string in an explicit interpolation:

// Before (crashes in preview):
logger.debug("User completed onboarding")
 
// After (works in preview):
logger.debug("\(String("User completed onboarding"))")

By making the argument an interpolation expression \(...), the preview compiler no longer sees a bare string literal and does not inject __designTimeString. The compiler correctly creates the OSLogInterpolation, and the preview builds successfully.

Apply it everywhere

You need to fix every Logger call that uses a plain string literal in files that are part of your preview's compilation. A quick way to find them:

# Find logger calls with plain string literals
grep -rn 'logger\.\(debug\|info\|warning\|error\|notice\|fault\)("' Sources/

If you have many log statements, you can also create a helper that takes a plain String and uses print or a conditional #if DEBUG fallback during previews, though the interpolation wrapper is the most targeted fix.

Why not just use print?

OSLog.Logger is significantly better than print for production apps:

  • Structured log levels (debug, info, error, fault)
  • Privacy controls for sensitive data
  • Visible in Console.app with filtering
  • Near-zero overhead when not actively observed

The preview issue is a tooling quirk, not a reason to abandon OSLog.