本記事では Ruby でよく発生するエラー、
syntax error, unexpected end-of-input, expecting `end'
の原因と解決手順について解説します。

いままで100名以上のプログラミング学習をサポートしてきましたが、学習初期のころにはよく発生するエラーです。
ここで解説する方法を使えばみなさんすぐに解決できるようになりました。
このエラーは理由を理解すればある程度機械的に解決できるからです。
この記事を読めばこのエラーを解決できる力が身につきます。
原因:end キーワードが足りない
プログラムコードに end キーワードが足りないときに発生します。
エラーメッセージ
syntax error, unexpected end-of-input, expecting `end'
を確認しながら解説していきます
解説

syntax error は構文エラーと言う意味です。
Ruby の構文に適合しない書き方がされているということです。
unexpected end-of-input で「予期しない入力の最後」という意味になります。
end-of-input は「入力の最後」くらいの意味です。「ファイルの最後」と捉えてもオーケーです。
Ruby はプログラムコードを一行目から順番に構文チェックしていくのですが、最後の行にたどり着いたときに、「構文上まだあるはずなのに終わってしまった・・・」ということで
最後までプログラムコードを読んだけどまだなにかあるはずですよ!
という意味をこめて「予期しない入力の最後」というエラーメッセージを出力しているのです。
expecting `end’ は、「end (というキーワード) が予期されます」という意味です。
つまり、「次は end が来るはず、と思っていたけど無かったよ!」と意訳できます。
整理すると
- 構文上のエラー
- 最後までプログラムコードを読んだけどまだなにかあるはず
- 期待していたのは「end キーワード」
ということです。
これらを総合して考えると
最後まで見たら、構文上あるはずの end がない!
ということになります。
前提知識:end が必要な構文を把握しよう
このエラーに対応するためには end が必要な構文を覚えておく必要があります。
よく使う end が必要な構文を一覧します。
end が必要な構文
- class 〜 end
- module 〜 end
- def 〜 end
- if 〜 end
- unless 〜 end
- when 〜 end
- while 〜 end
- do 〜 end
- begin 〜 end
これらの対応を意識してコードを確認することが大切です。
ただし、
return if admin?
のような、後置 if の場合は end が不要なので注意が必要です。
解決手順
エラーの解決手順を解説します。
① インデントを正しくする
まずは、インデントを正しくして end キーワードの対応関係を見やすくします。
インデントとは字下げのことで、入れ子構造を見やすくするために必要な書き方です。
例えば以下のプログラムはどうでしょう。
class PostsController < ApplicationController
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
flash[:success] = 'Success!'
redirect_to @post
else
flash.now[:danger] = 'Failed to create post!'
render :new
end
def post_params
params.require(:post).permit(:content)
end
end
ぱっと見るだけでもとても読みづらいと思います。
xxx 〜 end の対応をとるのも簡単ではありません。
これをインデントを正しくする(= 入れ子の中身を字下げをする)とこうなります。
class PostsController < ApplicationController
def index
@posts = Post.all
end
def show
@post = Post.find(params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
flash[:success] = 'Success!'
redirect_to @post
else
flash.now[:danger] = 'Failed to create post!'
render :new
end
def post_params
params.require(:post).permit(:content)
end
end
圧倒的に見やすいですし、xxx 〜 end の対応関係もとりやすいのではないでしょうか。
対応関係はこんな感じです。

② メソッド単位で xxx 〜 end の組み合わせを確認する
メソッド単位で分割していきます。

すると create メソッドの end が足りないことに気づくと思います。

③ 修正する
end が無い箇所が分かったら追加してあげましょう。
class PostsController < ApplicationController
def index
@posts = Post.all
end
def show
@post = Post.find(params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
flash[:success] = 'Success!'
redirect_to @post
else
flash.now[:danger] = 'Failed to create post!'
render :new
end
end # ← ここに end を追加
def post_params
params.require(:post).permit(:content)
end
end
これで治ります。
今回は def に対応する end が見つからない場合でした。
その他のパターンとして if や class など他のキーワードに対応する end が足りない場合もあります。
必要に応じて付け足してあげましょう。
まとめ
unexpected end-of-input, expecting `end’ の原因と解決手順について解説しました。
このエラーは普段から「開いたら閉じる」を意識しておくと未然に防げるエラーです。
「開いたら閉じる」は xxx 〜 end だけではなく、
- 文字列: “…”、 ‘…’
- カッコ: ( )、 { }、[ ]
なども同様です。
- カッコを開いたら、中身を書く前にカッコを閉じる
- 閉じてから中身を書いていく
のような習慣をつけておくといいでしょう。
その他の Rails エラー関連記事はこちら