Sass @warn Rule

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
Soft warn · keep compiling

What You’ll Learn

Sass @warn prints a message and stack trace without stopping compilation. This page covers syntax, deprecation warnings, soft validation, how @warn differs from @error and @debug, and five compiled examples.

01

Warn

@warn

02

Continue

CSS still ships

03

Deprecate

Legacy args

04

Trace

Call stack

05

Vs error

Soft vs hard

06

Practice

5 examples

What Is @warn?

Official docs: when writing mixins and functions, you may want to discourage users from passing certain arguments or values. They may be passing legacy arguments that are now deprecated, or calling your API in a way that is not quite optimal.

The @warn rule is written @warn <expression>. It prints the value (usually a string) plus a stack trace showing how the current mixin or function was called. Unlike @error, it does not stop Sass entirely.

  • Warnings appear in the compiler / terminal / build log—not in the CSS file.
  • Compilation continues, so CSS is still produced.
  • Ideal for deprecations, typos you still handle, and soft API tips.
  • Message format and stack traces vary by Sass implementation.
💡
Beginner tip

Think of @warn as a yellow caution light: “this still works, but you should fix it.” Use @error when the light should turn red and stop the build.

📝 Syntax

styles.scss
@use "sass:list";

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not list.index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

Warn inside the branch that detects the problem, then continue with a sensible fallback or the original behavior so existing stylesheets keep compiling.

📤 Messages & Stack Traces

Official docs: the exact format of the warning and stack trace varies from implementation to implementation. In Dart Sass it often looks like this:

styles.scss
WARNING: Unknown prefix wekbit.
    example.scss 6:7   prefix()
    example.scss 16:3  root stylesheet
💡
Write actionable warnings

Say what happened and what to do next: "The xl size is deprecated. Use lg instead." is clearer than "Deprecated."

⚖️ @warn vs @error vs @debug

At-ruleStops compile?Best for
@warnNoDeprecations, soft tips, recoverable mistakes
@errorYesInvalid API usage that must not continue
@debugNoInspecting values while developing

Choose @warn when CSS can still be correct (or safely remapped). Choose @error when emitting CSS would be wrong or dangerous.

🛡️ Common @warn Patterns

  • Unknown but tolerated values — typo’d vendor prefixes still emit.
  • Deprecations — old size names remap to new ones with a warning.
  • Soft type fallbacks — wrong type gets a default plus a warning (prefer @error for public APIs when possible).
  • Missing map keys — fall back to a default theme token.
  • Alias functionsfg() warns and forwards to foreground().

⚡ Quick Reference

GoalCode
Soft warning@warn "Message here.";
Include a value@warn "Unknown prefix #{$prefix}.";
Deprecate + remap@warn "…"; $size: lg;
Keep compilingDo not use @error
Hard fail insteadUse @error
Inspect a valueUse @debug

Examples Gallery

Each example still produces CSS. Open View Compiled CSS and View Compiler Warning to see both sides of @warn.

📚 Getting Started

Warn about bad input, then keep emitting styles.

Example 1 — Unknown Prefix Tip

Official-style mixin: warn on a typo, but still output the prefix.

styles.scss
@use "sass:list";

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not list.index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

How It Works

wekbit is not in $known-prefixes, so Sass warns—but the mixin still emits -wekbit-transform and the real transform.

Example 2 — Deprecate & Remap

Warn about a legacy size, then map it to the modern value.

styles.scss
@mixin button($size: md) {
  @if $size == xl {
    @warn "The xl size is deprecated. Use lg instead.";
    $size: lg;
  }

  @if $size == sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.875rem;
  } @else if $size == md {
    padding: 0.5rem 1rem;
    font-size: 1rem;
  } @else {
    padding: 0.75rem 1.25rem;
    font-size: 1.125rem;
  }
}

.cta {
  @include button(xl);
}

How It Works

Callers using xl keep working during a migration window, but the warning nudges them toward lg.

📈 Fallbacks, Themes & Aliases

Recoverable mistakes and migration helpers.

Example 3 — Soft Type Fallback

Warn on a bad type, return a safe default, and keep compiling.

styles.scss
@use "sass:meta";
@use "sass:math";

@function scale-opacity($value) {
  @if meta.type-of($value) != number {
    @warn "scale-opacity() expected a number; got #{meta.type-of($value)}. Using 1.";
    @return 1;
  }
  @return math.div($value, 100);
}

.card {
  opacity: scale-opacity(80);
}

.broken {
  opacity: scale-opacity("eighty");
}

How It Works

Valid input becomes 0.8. Invalid input warns and falls back to 1. For a strict public API, prefer @error instead of a silent-ish default.

Example 4 — Unknown Theme Key

Fall back to primary when a token name is missing.

styles.scss
@use "sass:map";

@mixin theme-color($name) {
  $palette: (
    primary: #036,
    accent: #c45,
  );

  @if not map.has-key($palette, $name) {
    @warn "Unknown theme color `#{$name}`. Falling back to primary.";
    $name: primary;
  }

  color: map.get($palette, $name);
}

.text {
  @include theme-color(accent);
}

.miss {
  @include theme-color(neon);
}

How It Works

accent resolves normally. neon warns and uses primary so the page still has a color.

Example 5 — Deprecated Function Alias

Keep an old name working while steering callers to the new one.

styles.scss
@function fg($args...) {
  @warn "The fg() function is deprecated. Call foreground() instead.";
  @return foreground($args...);
}

@function foreground($color) {
  @return $color;
}

.title {
  color: fg(#222);
}

How It Works

$args... forwards every argument to foreground(). Callers keep working while the warning pushes migration.

🚀 Real-World Use Cases

  • API migrations — deprecate old argument names with a remap.
  • Design-system releases — warn before removing a token in the next major.
  • Typo detection — unknown prefixes or theme keys that still compile.
  • Alias shims — keep fg() while promoting foreground().
  • CI visibility — surface warnings in build logs without failing (unless you treat warnings as errors).

🧠 How Compilation Works

1

Call a mixin/function

Someone passes a legacy, odd, or mistyped argument.

Source
2

Hit @warn

Sass prints the message and a short stack trace.

Warn
3

Keep going

Your code remaps, falls back, or continues as written.

Continue
4

CSS ships

Styles emit; the warning stays in the build log.

⚠️ Common Pitfalls

  • Using @warn for fatal mistakes — if CSS would be wrong, use @error.
  • Vague messages — always say what to use instead.
  • Warning spam — avoid warning on every loop iteration when one summary is enough.
  • Assuming users see warnings — some CI setups hide or ignore them.
  • Forever deprecations — plan a timeline to remove the old path.

💡 Best Practices

✅ Do

  • Warn + remap during API migrations
  • Include the bad value and the recommended fix
  • Prefer one clear warning per call site issue
  • Graduate hard breaks to @error in a later major
  • Keep aliases thin: warn, then call the real API

❌ Don’t

  • Use @warn when the build must fail
  • Hide broken output behind soft warnings forever
  • Write warnings without a migration path
  • Confuse @warn with @debug for temporary prints
  • Assume warnings appear in the CSS file

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass @warn

Soft guidance with a stack trace—compilation keeps going.

5
Core concepts
🔀 02

Continue

CSS still emits

Build
📤 03

Guide

got vs preferred

Message
📈 04

Migrate

deprecate + remap

API
05

Choose

warn ≠ error

Soft

❓ Frequently Asked Questions

It prints the value of an expression (usually a string) plus a stack trace for the user, but unlike @error it does not stop Sass from compiling the stylesheet.
Use it to discourage legacy or suboptimal arguments, flag typos that you still handle, announce deprecations, or guide callers without breaking their build.
@warn continues compilation and still emits CSS. @error aborts the compile. Prefer @error when continuing would produce broken output.
No. Warnings go to the compiler / terminal / build log. The CSS may still include whatever styles your mixin emitted after the warning.
Build tools and Sass CLIs often have quiet or fatal-warning options. Exact flags depend on your Sass version and bundler—check Dart Sass docs for --quiet and related options.
No. Soft warnings are for recoverable cases. If the API cannot continue safely, use @error instead.
Did you know?

Official Sass docs designed @warn specifically so library authors can discourage legacy or suboptimal arguments without breaking every consumer’s build overnight.

Conclusion

@warn is your soft signal for Sass APIs: print a clear message, keep compiling, and give callers time to migrate. Reserve @error for cases where continuing would ship broken CSS.

Continue with @debug or @error.

Next: Sass @debug

Print variables and expressions with file + line while CSS still compiles.

@debug rule →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful