diff --git a/src/atrule/mod.rs b/src/atrule/mod.rs
index 42a967f..8a48ab6 100644
--- a/src/atrule/mod.rs
+++ b/src/atrule/mod.rs
@@ -13,8 +13,8 @@ use crate::{Stmt, Token};
 
 pub(crate) use function::Function;
 pub(crate) use if_rule::If;
-pub(crate) use mixin::{eat_include, Mixin};
 pub(crate) use kind::AtRuleKind;
+pub(crate) use mixin::{eat_include, Mixin};
 use parse::eat_stmts;
 use unknown::UnknownAtRule;
 
@@ -28,7 +28,6 @@ mod unknown;
 
 #[derive(Debug, Clone)]
 pub(crate) enum AtRule {
-    Error(Pos, String),
     Warn(Pos, String),
     Debug(Pos, String),
     Mixin(String, Box<Mixin>),
@@ -54,11 +53,13 @@ impl AtRule {
         devour_whitespace(toks);
         Ok(match rule {
             AtRuleKind::Error => {
-                let message = toks
-                    .take_while(|x| x.kind != ';')
-                    .map(|x| x.kind.to_string())
-                    .collect::<String>();
-                AtRule::Error(pos, message)
+                let message = Value::from_vec(
+                    read_until_semicolon_or_closing_curly_brace(toks),
+                    scope,
+                    super_selector,
+                )?;
+
+                return Err(message.to_string().into());
             }
             AtRuleKind::Warn => {
                 let message = toks
diff --git a/src/lib.rs b/src/lib.rs
index 6a44c8c..d061401 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -372,7 +372,6 @@ impl<'a> StyleSheetParser<'a> {
                                         insert_global_fn(&name, *func);
                                     }
                                     AtRule::Charset => continue,
-                                    AtRule::Error(pos, message) => self.error(pos, &message),
                                     AtRule::Warn(pos, message) => self.warn(pos, &message),
                                     AtRule::Debug(pos, message) => self.debug(pos, &message),
                                     AtRule::Return(_) => {
@@ -594,7 +593,6 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
                             AtRule::Charset => todo!("@charset as expr"),
                             AtRule::Debug(a, b) => Ok(Some(Expr::Debug(a, b))),
                             AtRule::Warn(a, b) => Ok(Some(Expr::Warn(a, b))),
-                            AtRule::Error(pos, err) => Err(SassError::new(err, pos)),
                             a @ AtRule::Return(_) => Ok(Some(Expr::AtRule(a))),
                             c @ AtRule::Content => Ok(Some(Expr::AtRule(c))),
                             f @ AtRule::If(..) => Ok(Some(Expr::AtRule(f))),
@@ -651,29 +649,4 @@ impl<'a> StyleSheetParser<'a> {
             pos.column()
         );
     }
-
-    fn error(&self, pos: Pos, message: &str) -> ! {
-        eprintln!("Error: {}", message);
-        eprintln!(
-            "{} {}:{} todo!(scope) on line {} at column {}",
-            self.file,
-            pos.line(),
-            pos.column(),
-            pos.line(),
-            pos.column()
-        );
-        let padding = vec![' '; format!("{}", pos.line()).len() + 1]
-            .iter()
-            .collect::<String>();
-        eprintln!("{}|", padding);
-        eprint!("{} | ", pos.line());
-        eprintln!("todo! get line to print as error");
-        eprintln!(
-            "{}| {}^",
-            padding,
-            vec![' '; pos.column() as usize].iter().collect::<String>()
-        );
-        eprintln!("{}|", padding);
-        std::process::exit(1);
-    }
 }
diff --git a/src/value/parse.rs b/src/value/parse.rs
index b2ce78f..b69d14c 100644
--- a/src/value/parse.rs
+++ b/src/value/parse.rs
@@ -366,6 +366,14 @@ impl Value {
         })
     }
 
+    pub fn from_vec(
+        toks: Vec<Token>,
+        scope: &Scope,
+        super_selector: &Selector,
+    ) -> SassResult<Value> {
+        Self::from_tokens(&mut toks.into_iter().peekable(), scope, super_selector)
+    }
+
     fn ident<I: Iterator<Item = Token>>(
         toks: &mut Peekable<I>,
         scope: &Scope,