diff --git a/ash/capture_mode/action_button_container_view.cc b/ash/capture_mode/action_button_container_view.cc
index 2d235c22c9f8f..783db7bc5130d 100644
--- a/ash/capture_mode/action_button_container_view.cc
+++ b/ash/capture_mode/action_button_container_view.cc
@@ -11,24 +11,35 @@
 
 #include "ash/capture_mode/action_button_view.h"
 #include "ash/capture_mode/capture_mode_types.h"
+#include "ash/capture_mode/capture_mode_util.h"
+#include "ash/style/system_shadow.h"
+#include "ash/style/typography.h"
 #include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/ranges/algorithm.h"
 #include "base/time/time.h"
 #include "ui/aura/window.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/views/animation/animation_builder.h"
+#include "ui/views/background.h"
 #include "ui/views/controls/button/button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/box_layout_view.h"
+#include "ui/views/vector_icons.h"
 #include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
 #include "ui/views/view_utils.h"
 #include "ui/views/widget/widget.h"
 
@@ -36,6 +47,19 @@ namespace ash {
 
 namespace {
 
+// Horizontal spacing between the error view and action buttons.
+constexpr int kErrorViewActionButtonSpacing = 6;
+
+constexpr auto kErrorViewBorderInsets = gfx::Insets::TLBR(8, 8, 8, 12);
+
+constexpr int kErrorViewCornerRadius = 18;
+
+constexpr int kErrorViewLeadingIconSize = 20;
+
+// Padding to the right of the error view's leading icon, to separate the icon
+// from the error message label.
+constexpr auto kErrorViewLeadingIconRightPadding = 4;
+
 // The horizontal distance between action buttons in a row.
 constexpr int kActionButtonSpacing = 10;
 
@@ -56,8 +80,82 @@ constexpr base::TimeDelta kSmartActionsButtonTransitionSlideInDuration =
 
 }  // namespace
 
+ActionButtonContainerView::ErrorView::ErrorView()
+    : shadow_(SystemShadow::CreateShadowOnTextureLayer(
+          SystemShadow::Type::kElevation12)) {
+  SetOrientation(views::BoxLayout::Orientation::kHorizontal);
+  SetInsideBorderInsets(kErrorViewBorderInsets);
+
+  SetBackground(views::CreateThemedRoundedRectBackground(
+      cros_tokens::kCrosSysSystemBaseElevated,
+      gfx::RoundedCornersF(kErrorViewCornerRadius)));
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+  shadow_->SetRoundedCornerRadius(kErrorViewCornerRadius);
+  capture_mode_util::SetHighlightBorder(
+      this, kErrorViewCornerRadius,
+      views::HighlightBorder::Type::kHighlightBorderNoShadow);
+
+  AddChildView(views::Builder<views::ImageView>()
+                   .SetPreferredSize(gfx::Size(kErrorViewLeadingIconSize,
+                                               kErrorViewLeadingIconSize))
+                   .SetImage(ui::ImageModel::FromVectorIcon(
+                       views::kInfoIcon, cros_tokens::kCrosSysSecondary))
+                   .SetProperty(views::kMarginsKey,
+                                gfx::Insets::TLBR(
+                                    0, 0, 0, kErrorViewLeadingIconRightPadding))
+                   .Build());
+
+  AddChildView(
+      views::Builder<views::Label>()
+          .CopyAddressTo(&error_label_)
+          .SetEnabledColorId(cros_tokens::kCrosSysSecondary)
+          .SetFontList(TypographyProvider::Get()->ResolveTypographyToken(
+              TypographyToken::kCrosAnnotation1))
+          .Build());
+}
+
+ActionButtonContainerView::ErrorView::~ErrorView() = default;
+
+void ActionButtonContainerView::ErrorView::AddedToWidget() {
+  views::BoxLayoutView::AddedToWidget();
+
+  // Attach the shadow at the bottom of the widget layer.
+  ui::Layer* shadow_layer = shadow_->GetLayer();
+  ui::Layer* widget_layer = GetWidget()->GetLayer();
+  widget_layer->Add(shadow_layer);
+  widget_layer->StackAtBottom(shadow_layer);
+
+  // Make the shadow observe the color provider source change to update the
+  // colors.
+  shadow_->ObserveColorProviderSource(GetWidget());
+}
+
+void ActionButtonContainerView::ErrorView::OnBoundsChanged(
+    const gfx::Rect& previous_bounds) {
+  // The shadow layer is a sibling of this view's layer, and should have the
+  // same bounds.
+  shadow_->SetContentBounds(layer()->bounds());
+}
+
+void ActionButtonContainerView::ErrorView::SetErrorMessage(
+    const std::u16string& error_message) {
+  error_label_->SetText(error_message);
+}
+
+const std::u16string&
+ActionButtonContainerView::ErrorView::GetErrorMessageForTesting() const {
+  return error_label_->GetText();
+}
+
 ActionButtonContainerView::ActionButtonContainerView() {
-  SetUseDefaultFillLayout(true);
+  auto* box_layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kHorizontal));
+  box_layout->set_between_child_spacing(kErrorViewActionButtonSpacing);
+
+  error_view_ = AddChildView(std::make_unique<ErrorView>());
+  error_view_->SetVisible(false);
+
   AddChildView(
       views::Builder<views::BoxLayoutView>()
           .CopyAddressTo(&action_button_row_)
@@ -124,6 +222,16 @@ const views::View::Views& ActionButtonContainerView::GetActionButtons() const {
   return action_button_row_->children();
 }
 
+void ActionButtonContainerView::ShowErrorView(
+    const std::u16string& error_message) {
+  error_view_->SetErrorMessage(error_message);
+  error_view_->SetVisible(true);
+}
+
+void ActionButtonContainerView::HideErrorView() {
+  error_view_->SetVisible(false);
+}
+
 void ActionButtonContainerView::StartSmartActionsButtonTransition() {
   views::Widget* widget = GetWidget();
   if (!widget) {
@@ -214,6 +322,9 @@ void ActionButtonContainerView::SetWidgetEventsEnabled(bool enabled) {
               : aura::EventTargetingPolicy::kNone);
 }
 
+BEGIN_METADATA(ActionButtonContainerView, ErrorView)
+END_METADATA
+
 BEGIN_METADATA(ActionButtonContainerView)
 END_METADATA
 
diff --git a/ash/capture_mode/action_button_container_view.h b/ash/capture_mode/action_button_container_view.h
index cffce6f621f1b..26a7059355c3f 100644
--- a/ash/capture_mode/action_button_container_view.h
+++ b/ash/capture_mode/action_button_container_view.h
@@ -5,6 +5,7 @@
 #ifndef ASH_CAPTURE_MODE_ACTION_BUTTON_CONTAINER_VIEW_H_
 #define ASH_CAPTURE_MODE_ACTION_BUTTON_CONTAINER_VIEW_H_
 
+#include <memory>
 #include <string>
 
 #include "ash/ash_export.h"
@@ -13,21 +14,53 @@
 #include "base/memory/weak_ptr.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/button/button.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/view.h"
 
 namespace gfx {
 struct VectorIcon;
 }  // namespace gfx
 
+namespace views {
+class Label;
+}
+
 namespace ash {
 
 class ActionButtonView;
+class SystemShadow;
 
-// A view that displays a row of action buttons near the capture region.
+// A view that displays a row of action buttons near the capture region. It may
+// display an error message if actions are not available.
 class ASH_EXPORT ActionButtonContainerView : public views::View {
   METADATA_HEADER(ActionButtonContainerView, views::View)
 
  public:
+  // A view that displays an error message and icon.
+  class ASH_EXPORT ErrorView : public views::BoxLayoutView {
+    METADATA_HEADER(ErrorView, views::BoxLayoutView)
+
+   public:
+    ErrorView();
+    ErrorView(const ErrorView&) = delete;
+    ErrorView& operator=(const ErrorView&) = delete;
+    ~ErrorView() override;
+
+    // views::BoxLayoutView:
+    void AddedToWidget() override;
+    void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+
+    // Sets the error message to show on the error view.
+    void SetErrorMessage(const std::u16string& error_message);
+
+    const std::u16string& GetErrorMessageForTesting() const;
+
+   private:
+    std::unique_ptr<SystemShadow> shadow_;
+
+    raw_ptr<views::Label> error_label_ = nullptr;
+  };
+
   ActionButtonContainerView();
   ActionButtonContainerView(const ActionButtonContainerView&) = delete;
   ActionButtonContainerView& operator=(const ActionButtonContainerView&) =
@@ -50,12 +83,20 @@ class ASH_EXPORT ActionButtonContainerView : public views::View {
   // Returns the action buttons in this container.
   const views::View::Views& GetActionButtons() const;
 
+  // Shows an error view with the given `error_message`.
+  void ShowErrorView(const std::u16string& error_message);
+
+  // Hides the error view.
+  void HideErrorView();
+
   // Starts performing the button transition triggered after pressing the smart
   // actions button. This will fade out existing action buttons, remove the
   // smart actions button, then animate in new icon buttons to replace the old
   // copy text and search buttons.
   void StartSmartActionsButtonTransition();
 
+  const ErrorView* error_view_for_testing() const { return error_view_; }
+
  private:
   // Called when the smart actions button has faded out, to start the transition
   // to new buttons. See `StartSmartActionsButtonTransition()`.
@@ -67,6 +108,9 @@ class ASH_EXPORT ActionButtonContainerView : public views::View {
   // Contains the row of action buttons.
   raw_ptr<views::View> action_button_row_ = nullptr;
 
+  // Used to show an error message.
+  raw_ptr<ErrorView> error_view_ = nullptr;
+
   base::WeakPtrFactory<ActionButtonContainerView> weak_ptr_factory_{this};
 };
 
diff --git a/ash/capture_mode/action_button_container_view_unittest.cc b/ash/capture_mode/action_button_container_view_unittest.cc
index 778837c6a63ac..d753487cc44b2 100644
--- a/ash/capture_mode/action_button_container_view_unittest.cc
+++ b/ash/capture_mode/action_button_container_view_unittest.cc
@@ -124,5 +124,22 @@ TEST_F(ActionButtonContainerViewTest, SmartActionsButtonTransition) {
   EXPECT_TRUE(IsActionButtonCollapsed(search_button));
 }
 
+TEST_F(ActionButtonContainerViewTest, ShowsErrorView) {
+  ActionButtonContainerView action_button_container;
+  const ActionButtonContainerView::ErrorView* error_view =
+      action_button_container.error_view_for_testing();
+
+  EXPECT_FALSE(error_view->GetVisible());
+
+  action_button_container.ShowErrorView(u"Error message");
+
+  EXPECT_TRUE(error_view->GetVisible());
+  EXPECT_EQ(error_view->GetErrorMessageForTesting(), u"Error message");
+
+  action_button_container.HideErrorView();
+
+  EXPECT_FALSE(error_view->GetVisible());
+}
+
 }  // namespace
 }  // namespace ash