91³Ô¹ÏÍø

Watch CBS News

Minnesota Sen. John Hoffman, his wife undergo surgery after shooting at their home

A massive manhunt is underway for the suspect behind the fatal shooting of Minnesota state Rep. Melissa Hortman and her husband in Brooklyn Park. State Sen. John Hoffman and his wife were also injured in what Gov. Tim Walz called "politically motivated" shootings.

Police first responded to a call of a shooting at Hoffman's home in Champlin at around 2 a.m. Saturday, Drew Evans, the superintendent of the Minnesota Bureau of Criminal Apprehension, said in the briefing.

Investigators said the shooter was dressed as a police officer, and photos released by the FBI show the suspect wearing what appeared to be a mask.

Life-saving measures were provided to John Hoffman and his wife, Yvette Hoffman. They were taken to an area hospital, where they underwent surgery to treat gunshot wounds, Evans said.

He and his wife were each shot multiple times, Walz said. They are out of surgery and are receiving care, Walz said. He added that his "prayers are with" the couple.  

In a briefing, authorities describe John Hoffman's injuries as very serious. Both him and his wife are in stable condition.

Sunday evening, U.S. Sen. Amy Klobuchar posted on Facebook a screenshot of a text she says she received from Yvette Hoffman.

"Our family is so humbled by the love and outpouring from everyone," Yvette Hoffman writes in the text.

Yvette Hoffman says her husband was shot nine times and she was shot eight times.

"John is enduring many surgeries right now and is closer every hour to being out of the woods," she said. "...We are incredibly lucky to be alive. We are gutted and devestated by the loss of Melissa and Mark. We have no words. There is never a place for this kind of political hate."

Lawmakers speak out in support of Hoffman

Lawmakers have been speaking out over the shootings.

"I think everyone that knows John, knows a man with a tremendous sense of humor, and an enormous heart. That is John Hoffman. And I know I and colleagues on both sides of the aisle are praying for him and his wife have a speedy and full recovery," said Sen. Zach Duckworth (R-57), while speaking with WCCO. "He is a guy that has been dedicated to serving Minnesotans and Americans. So, we hope and pray that he ends up OK, and we can welcome him back to the Capitol to keep doing the phenomenal work he's done through his career."

Multiple law enforcement sources have identified a suspect being sought by investigators in connection with the shootings as 57-year-old Vance Luther Boelter, of Minnesota.  

The Federal Bureau of Investigation says it is offering a $50,000 reward for information leading to Boelter's arrest and conviction. 

Who is John Hoffman?

John Hoffman, 60, represents Minnesota Senate District 34, which covers a swath of the northwest Twin Cities suburbs, including Rogers and Champlin. He is also a member of the Democratic Party. 

John Hoffman was first elected to serve in 2012 and was reelected three times after.

He served as chair of the Human Services Committee, and also served on committees for energy, environment and health and human services.

He was born in 1965. He has one daughter, according to the Associated Press. 

View CBS News In
CBS News App Open
Chrome Safari Continue
const link = doc.createElement('link'); link.rel = 'stylesheet'; link.href = '/fly/fly/bundles/cbsnewscontent/css/cmp-banner.min.css?v=50747257b890e014813016b79ece0fb2'; doc.head.appendChild(link); doc.body.innerHTML = CONSENT_MESSAGE; } else { el.insertAdjacentHTML('afterend', CONSENT_MESSAGE); } }); } function hidePrivacyMessage() { // Remove from the main document document.querySelectorAll(`.${CONSENT_MESSAGE_CLASS}`).forEach(el => el.remove()); // Remove from inside any iframes document.querySelectorAll('iframe').forEach(iframe => { const doc = iframe.contentDocument || iframe.contentWindow.document; doc.querySelectorAll(`.${CONSENT_MESSAGE_CLASS}`).forEach(el => el.remove()); }); } function activateGatedScripts() { // Handle both new format (cmp-gated-script) and old OneTrust/Ketch format (optanon-category-4) const gatedScripts = Array.from(document.querySelectorAll('script.cmp-gated-script, script.optanon-category-4')); // Activate scripts sequentially with a small delay to avoid timing issues let delay = 0; gatedScripts.forEach(function(placeholder, index) { setTimeout(function() { // Skip if already processed if (placeholder.hasAttribute('data-cmp-processed')) { return; } placeholder.setAttribute('data-cmp-processed', 'true'); const newScript = document.createElement('script'); newScript.type = 'text/javascript'; // Try new format first (data-cmp-src), then fall back to old format (data-src) const src = placeholder.getAttribute('data-cmp-src') || placeholder.getAttribute('data-src'); if (src) { newScript.src = src; } else if (placeholder.textContent) { // Inline script - just copy the content newScript.textContent = placeholder.textContent; } // Handle new format attributes (data-cmp-attrs) - for both inline and external scripts const attrs = placeholder.getAttribute('data-cmp-attrs'); if (attrs) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = '
<\/div>'; const tempAttrs = tempDiv.firstChild.attributes; for (let i = 0; i < tempAttrs.length; i++) { // For external scripts, allow defer/async. For inline scripts, skip them (not valid) if (src || (tempAttrs[i].name !== 'async' && tempAttrs[i].name !== 'defer')) { newScript.setAttribute(tempAttrs[i].name, tempAttrs[i].value); } } } // Copy other attributes from old OneTrust format for (let i = 0; i < placeholder.attributes.length; i++) { const attr = placeholder.attributes[i]; // Skip attributes we've already handled or don't want to copy if (!['class', 'data-src', 'data-type', 'data-cmp-src', 'data-cmp-attrs', 'data-cmp-processed', 'type', 'async', 'defer', 'src'].includes(attr.name)) { newScript.setAttribute(attr.name, attr.value); } } placeholder.parentNode.replaceChild(newScript, placeholder); // If external script, manually trigger window.onload handlers after it loads // This handles widgets that use window.onload for initialization if (src) { newScript.addEventListener('load', function() { // If page already loaded and script set a new onload handler, trigger it if (document.readyState === 'complete' && window.onload) { const originalOnload = window.onload; window.onload = null; // Clear temporarily to prevent loops originalOnload(); // Execute the handler } }); } }, delay); delay += 500; // 500ms delay between each script to allow full loading }); } cbsoptanon.onScriptsReady(function(cmp) { cmp.ot.targetingAllowed(function(allowed) { if (!allowed) { showPrivacyMessage(); } else { activateGatedScripts(); } }); cmp.ot.awaitInitialConsent(function(consent_model) { cmp.ot.addOnConsentChangedHandler(function() { cmp.ot.targetingAllowed(function(allowed) { if (allowed) { hidePrivacyMessage(); activateGatedScripts(); } else { showPrivacyMessage(); } }); }); }); });