diff --git a/mlir/lib/Transforms/SymbolDCE.cpp b/mlir/lib/Transforms/SymbolDCE.cpp
--- a/mlir/lib/Transforms/SymbolDCE.cpp
+++ b/mlir/lib/Transforms/SymbolDCE.cpp
@@ -124,11 +124,9 @@
       // Lookup the symbols referenced by this use.
       resolvedSymbols.clear();
       if (failed(symbolTable.lookupSymbolIn(
-              op->getParentOp(), use.getSymbolRef(), resolvedSymbols))) {
-        return use.getUser()->emitError()
-               << "unable to resolve reference to symbol "
-               << use.getSymbolRef();
-      }
+              op->getParentOp(), use.getSymbolRef(), resolvedSymbols)))
+        // Ignore references to unknown symbols.
+        continue;
 
       // Mark each of the resolved symbols as live.
       for (Operation *resolvedSymbol : resolvedSymbols)
diff --git a/mlir/test/Transforms/test-symbol-dce.mlir b/mlir/test/Transforms/test-symbol-dce.mlir
--- a/mlir/test/Transforms/test-symbol-dce.mlir
+++ b/mlir/test/Transforms/test-symbol-dce.mlir
@@ -84,7 +84,17 @@
 
 // -----
 
+// Check that unknown symbol references are OK.
 module {
-  // expected-error@+1 {{unable to resolve reference to symbol}}
+  // CHECK-NOT: func private @dead_private_function
+  func private @dead_private_function()
+
+  // CHECK: func private @live_private_function
+  func private @live_private_function()
+
+  // CHECK: "live.user"() {uses = [@live_private_function]} : () -> ()
+  "live.user"() {uses = [@live_private_function]} : () -> ()
+
+  // CHECK: "live.user"() {uses = [@unknown_symbol]} : () -> ()
   "live.user"() {uses = [@unknown_symbol]} : () -> ()
 }