{"title":"Halt!","description":"Stop Amber V2 pipelines and return early from controller actions","section":"guides/controllers","version":"v2","path":"guides/controllers/halt","canonical_url":"https://amberframework.org/docs/v2/guides/controllers/halt","markdown_url":"https://amberframework.org/docs/v2/guides/controllers/halt.md","inherited":false,"content_markdown":"# Halt!\n\n`halt!` sets the current context body, plain-text content type, and status code.\nIt is most useful in a before filter, where setting context content prevents the\ncontroller action from running.\n\n**File: `src/controllers/admin_controller.cr` — place the filter and action\ninside `AdminController`.**\n\n```crystal\nclass AdminController < ApplicationController\n  before_action do\n    only :index do\n      halt!(403, \"Forbidden\") unless session[:admin_id]?\n    end\n  end\n\n  def index\n    render(\"index.ecr\")\n  end\nend\n```\n\n`halt!` marks the request context; it does not raise an exception that escapes\nordinary Crystal control flow. Inside an action, return an explicit response\nwhen later expressions must not run.\n\n**File: the controller that owns `show`, for example\n`src/controllers/admin_controller.cr` — replace that action body.**\n\n```crystal\ndef show\n  unless authorized?\n    return set_response(\n      body: \"Forbidden\",\n      status_code: 403,\n      content_type: \"text/plain\"\n    )\n  end\n\n  render(\"show.ecr\")\nend\n```\n\nAmber's redirect helper sets the `Location` header and uses the same context\nresponse mechanism.\n\n**File: a controller action under `src/controllers/` — return this expression\nat the point where request processing should redirect.**\n\n```crystal\nredirect_to location: \"/login\", status: 302\n```\n\nThe V1 Slang example and its claim that `halt!` interrupts any action like an\nexception are not copied into V2."}