0Pricing
Lua Academy · レッスン

error()関数

error()でエラーを発生させ、エラーレベルとメッセージを理解します。

「error()関数」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

エラーを発生させる

error(message, level)はLuaのエラーを発生させます。実行は停止し、pcallまたはxpcallで捕捉されるか、プログラムが終了するまで、エラーは呼び出しスタックを上へ伝播します。メッセージには文字列、テーブル、数値など、任意の値を指定できます。

local function divide(a, b)
  if b == 0 then
    error("division by zero")
  end
  return a / b
end

print(divide(10, 2))    -- 5.0
-- divide(10, 0)        -- ERROR: division by zero

エラーレベル

error()の2番目の引数は、エラーをどこで報告するかを制御します。レベル1(デフォルト)はerror()の呼び出し自体を示します。レベル2は呼び出し元を示します。レベル0では位置情報を追加しません。ライブラリ関数では、ユーザーのコードに原因があることを示すためにレベル2を使用します。

local function assertPositive(n, name)
  if n <= 0 then
    error((name or "value") .. " must be positive, got " .. n, 2)
    -- level 2: blame the caller, not this function
  end
  return n
end

local function compute(x)
  assertPositive(x, "x")   -- error points here if x <= 0
  return math.sqrt(x)
end

compute(-5)  -- error: "x must be positive, got -5" at compute() call

テーブルオブジェクトを使ったエラー

エラー値としてテーブルを渡すと、呼び出し元はエラーコード、メッセージ、コンテキストなどの構造化されたエラー情報を調べられます。単純な文字列よりも情報量が多く、プログラムからエラーを処理できます。

local function openDB(host, port)
  if port < 1 or port > 65535 then
    error({code="INVALID_PORT", port=port,
           msg="port out of range: " .. port})
  end
  -- ... connect
  return {host=host, port=port}
end

local ok, err = pcall(openDB, "localhost", -1)
if not ok and type(err) == "table" then
  print("Code:", err.code)    -- INVALID_PORT
  print("Port:", err.port)    -- -1
  print("Msg:", err.msg)
end

糖衣構文としてのassert()

assert(v, msg)はif not v then error(msg, 2) end; return v, ...と同等です。事前条件の確認に使う慣用的な方法です。vがtruthyの場合、assertはすべての引数を返すため、メソッドチェーンにも利用できます。

local function sqrt(n)
  assert(type(n) == "number", "expected number, got " .. type(n))
  assert(n >= 0, "sqrt of negative: " .. n)
  return math.sqrt(n)
end

print(sqrt(16))    -- 4.0
print(sqrt(2))     -- 1.4142...
-- sqrt("hi")      -- ERROR: expected number, got string

error()とreturn nil,errの違い

失敗を通知する規約には、error()(例外形式)とreturn nil, msg(関数型形式)の2つがあります。error()は、予期しない状態(プログラミング上のバグや契約違反)に使用します。nil, msgは、想定される失敗(ファイルが見つからない、ネットワークがタイムアウトするなど)に使用します。

-- Exception style (programming error)
local function mustExist(t, key)
  local v = t[key]
  if v == nil then error("required key missing: " .. key, 2) end
  return v
end

-- Functional style (expected failure)
local function findUser(id)
  -- ... database query
  return nil, "user not found"  -- expected: user may not exist
end

メタメソッド内のエラー

メタメソッド内でエラーを発生させることもできます。メタメソッドでエラーが発生すると、算術式など、その操作を引き起こしたコードへ伝播します。メタメソッドでは、無効な入力に対して必ず対策してください。

local SafeDiv = {}
SafeDiv.__index = SafeDiv

SafeDiv.__div = function(a, b)
  if b.value == 0 then
    error("SafeDiv: division by zero", 2)
  end
  return SafeDiv.new(a.value / b.value)
end

function SafeDiv.new(v)
  return setmetatable({value=v}, SafeDiv)
end

local a = SafeDiv.new(10)
local b = SafeDiv.new(0)
local ok, err = pcall(function() return a / b end)
print(ok, err)

カスタムエラー型

型付きエラーオブジェクトを作成するヘルパーを用意します。型タグを含めることで、呼び出し側が異なる種類のエラーを区別し、それぞれに適切に対処できるようにします。

local function newError(kind, msg, extra)
  return setmetatable(
    {kind=kind, message=msg, extra=extra},
    {__tostring = function(e)
      return "[" .. e.kind .. "] " .. e.message
    end}
  )
end

local E = {
  notFound = function(name) return newError("NOT_FOUND","not found: "..name) end,
  badInput = function(msg)  return newError("BAD_INPUT", msg) end,
}

local ok, err = pcall(error, E.notFound("config.json"))
if not ok then print(err.kind, err.message) end

エラーの伝播

ある関数がエラーを返す別の関数を呼び出すと、そのエラーは自動的にスタックを上へ伝播します。再スローする必要はありません。単に捕捉しなければよいのです。エラーを意味のある形で処理または報告できるレベルでのみ、エラーを捕捉してください。

local function step3() error("step3 failed") end
local function step2() step3() end
local function step1() step2() end

local ok, err = pcall(step1)
if not ok then
  -- err includes the source location
  print("Caught at top level:", err)
end
-- Error: input:1: step3 failed

debug.traceback によるスタックトレース

通常の error() では、コンテキストが1行だけ示されます。完全なスタックトレースが必要な場合は、エラー値として debug.traceback(msg) を使用します。これは通常、xpcall のハンドラーで行います。

local function buggy()
  local t = nil
  return t.field   -- nil indexing: error
end

local ok, err = xpcall(buggy, function(e)
  return debug.traceback(e, 2)  -- full stack trace
end)

if not ok then
  print(err)  -- full traceback
end

エラーの再スロー

エラーを捕捉してコンテキストを追加した後、再スローすることがあります。文字列エラーを再スローする際は、すでに整形されたメッセージに位置情報のプレフィックスが追加されないよう、error(err, 0)(レベル0)を使用します。

local function loadAndParse(path)
  local ok, err = pcall(function()
    local f = io.open(path, "r")
    if not f then error("cannot open: " .. path) end
    local content = f:read("a")
    f:close()
    return content
  end)
  if not ok then
    error("loadAndParse failed: " .. err, 0)  -- re-raise with context
  end
end

local ok2, msg = pcall(loadAndParse, "missing.txt")
print(ok2, msg)

理解度チェック

error("msg", 2) のレベル2は何を意味しますか?

まとめ: error()

まとめ:

  • error(msg, level) — エラーを発生させます。レベル2では呼び出し元が原因として示されます
  • 型とコンテキストを持つ構造化エラーにはテーブルを使用します
  • assert(v, msg) — 慣用的な事前条件チェックです
  • バグには error() を使用し、予期される失敗には nil+err を返します
  • メッセージ形式を保持するには error(err, 0) で再スローします

よくある質問

「error()関数」レッスンは無料ですか?

はい。「error()関数」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「error()関数」で何を学びますか?

error()でエラーを発生させ、エラーレベルとメッセージを理解します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「error()関数」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. error()関数
  2. pcallによる保護付き呼び出し
  3. xpcallとメッセージハンドラー
  4. 構造化エラーオブジェクト
← Lua Academyに戻る