例外

目次

VMWare のふしぎ

Windows 上で VMWare を動かして CIFS を使っているときに VM を一時停止すると CIFS が同期されなくなってしまい、停止から復帰するときに不可解なエラー ("The Mongo object has not been correctly initialized by its constructor") が発生します。 Windows 共有を常にマウントさせるようにするとこの問題は発生せず、 自由に一時停止・再開をすることができます。

Windows 共有を常にマウントさせるには、次のコマンドを実行します。

$ sudo update-rc.d -f umountnfs.sh remove
$ sudo update-rc.d umountnfs.sh stop 15 0 6 .

最新情報については、 » Ubuntu のドキュメント を参照ください。

MongoException クラス

はじめに

Mongo のデフォルトの例外です。

さまざまなエラー条件を扱います。最終的にはより詳細な例外にたどり着きますが、 それらもすべて MongoException を継承しています。

  • The MongoSomething object has not been correctly initialized by its constructor

    コード: 0

    おそらく、Mongo オブジェクトがデータベースに接続していないものと思われます。

  • zero-length keys are not allowed, did you use $ with double quotes?

    コード: 1

    キーとして "" を使おうとしました。一般的に、これはしていはいけないことです。 "" を使うとサブオブジェクトへのアクセスが煩雑になり、またこのキーは MongoDB が内部的に使ってもいます。しかし、どうしても使いたい場合は、php.ini ファイルで mongo.allow_empty_keys に true を設定すればこのチェックを回避できます。 回避するよう設定した場合は、エラーチェックをより厳密に行って 文字列書き込みエラーを防ぐことを推奨します。

  • '.' not allowed in key: <key>

    コード: 2

    '.' を含むキーに書き込もうとしました。これは禁じられています。

  • insert too large: <size>, max: <max>

    コード: 3

    長すぎるデータをデータベースに一度に送ろうとしました。データベースがデータの追加を受け付けるのは、 ある特定の大きさ (現在は 16 MB) までです。

  • no elements in doc

    コード: 4

    フィールドを持たないドキュメントを保存しようとしました。

  • size of BSON doc is <size> bytes, max <max>MB

    コード: 5

    MongoDB で保存可能な長さを超えるドキュメントを保存しようとしました。

  • no documents given

    コード: 6

    空のドキュメントの配列を一括追加しようとしました。

  • MongoCollection::group takes an array, object, or MongoCode key

    コード: 7

    間違った型パラメータを MongoCollection::group に送信しました。

  • field names must be strings

    コード: 8

    フィールドセレクタの書式は array("field1" => 1, "field2" => 1, ..., "fieldN" => 1) としなければなりません。

  • invalid regex

    コード: 9

    MongoRegex に渡した正規表現が正しい形式ではありません。

  • MongoDBRef::get: $ref field must be a string

    コード: 10

  • MongoDBRef::get: $db field must be a string

    コード: 11

  • non-utf8 string: <str>

    コード: 12

    このエラーが発生するのは、非 utf8 文字列をデータベースに送信しようとしたときです。 データベースに送る文字列はすべて UTF8 でなければなりません。 この例外を発生させなくする移行用オプションは、php.ini のオプションを参照ください。

  • mutex error: <err>

    コード: 13

    マルチスレッド環境では、ドライバはリクエストとレスポンスの同期にミューテックスを使います。 これはきわめて深刻なエラーで、スタックトレースもないかもしれません。 めったに発生しないエラーなので、システムの情報と可能な限りの再現手順を添えてメンテナに報告しましょう。

  • index name too long: <len>, max <max> characters

    コード: 14

    128 文字を超える名前のインデックスは作れません。このエラーが発生した場合は、 MongoCollection::ensureIndex の "name" オプションを使って短いインデックス名をつけなければなりません。

クラス概要

MongoException
class MongoException extends Exception {
}

MongoResultException クラス

はじめに

MongoResultException は ( MongoCollection::findAndModify など) いくつかのコマンドヘルパーで、失敗した場合にスローする例外です。 元の結果ドキュメントは MongoResultException::getDocument で取得できます。

クラス概要

MongoResultException
class MongoResultException extends MongoException {
/* プロパティ */
public $document ;
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* メソッド */
public array getDocument ( void )
}

プロパティ

document

生の結果ドキュメントの配列。

MongoCursorException クラス

はじめに

カーソルへの不正なアクセスや応答を受け取る際のエラーが原因です。 このエラーが発生するのは、単なるクエリではなく結果を受け取るリクエストであることに注意しましょう。 書き込みやコマンド、あるいはその他何らかの情報をデータベースに送って結果を待つ操作では MongoCursorException をスローすることがあります。 唯一の例外は new MongoClient() (新しい接続の作成) で、これは MongoConnectionException しかスローしません。

このクラスはエラーメッセージを返します。 このメッセージを見れば、問題の調査の助けになり、 エラーコードに関連付けられた原因もわかります。

たとえば、次のように同じ _id のドキュメントを 2 件追加してみましょう。

<?php

try {
    
$collection->insert(array("_id" => 1), array("w" => 1));
    
$collection->insert(array("_id" => 1), array("w" => 1));
}
catch (
MongoCursorException $e) {
    echo 
"error message: ".$e->getMessage()."\n";
    echo 
"error code: ".$e->getCode()."\n";
}

?>
結果はこのようになります。
error message: E11000 duplicate key error index: foo.bar.$_id_  dup key: { : 1 }
error code: 11000
MongoDB のエラーコード (11000) が PHP のエラーコードとして使われていることに注目しましょう。 PHP のドライバは、可能な限り「ネイティブの」エラーコードを使います。

よくあるエラーとそのコード、そして原因をまとめました。

  • cannot modify cursor after beginning iteration

    コード: 0

    クエリを実行した後で、クエリの設定を変えるメソッドをコールしました。 いったんカーソルをリセットしてからやりなおしてください。

    An example:

    <?php

    try {
        
    $cursor $collection->find();
        
    var_dump($cursor->getNext());

        
    // getNext() でクエリを実行しているので、ここでリミットを指定しても遅すぎます
        
    $cursor->limit(1);
    }
    catch (
    MongoCursorException $e) {
        echo 
    "error message: ".$e->getMessage()."\n";
        echo 
    "error code: ".$e->getCode()."\n";
    }

    // こうすれば、正しく動作します
    $cursor->getNext();
    $cursor->reset();
    $cursor->limit(1);

    ?>

  • Get next batch send errors

    コード: 1

    クエリをデータベースに送信できませんでした。 データベースが立ち上がっていることとネットワークが正常であることを確認してください。

  • cursor not found

    コード: 2

    ドライバがデータベースから結果を取得しようとしましたが、 データベース側にクエリが残っていませんでした。 たいていは、カーソルがサーバー側でタイムアウトしたことを意味します。 やりとりがない状況が数秒続くと、データベースはカーソルを消します (これを防ぐための方法は MongoCursor::immortal を参照ください)。

    例を示します。

    <?php

    try {
        
    $cursor $collection->find();
        
    $cursor->getNext();

        
    // 15 分間スリープします
        
    sleep(60*15);

        while (
    $cursor->hasNext()) {
            
    $cursor->getNext();
        }
    }
    catch (
    MongoCursorException $e) {
        echo 
    "error message: ".$e->getMessage()."\n";
        echo 
    "error code: ".$e->getCode()."\n";
    }

    ?>

  • cursor->buf.pos is null

    コード: 3

    これは、RAM から外れてしまったか、 その他の異常な状況になったことを意味します。

  • couldn't get response header

    コード: 4

    データベースあるいはネットワークがダウンしているときによく出るエラーです。 ドライバが接続からの応答を受け取れなかったことを意味します。

  • no db response

    コード: 5

    これはエラーではないかもしれません。たとえば、データベースの "shutdown" コマンドは何も応答を返しません。 しかし、もし何らかの応答を得ることを期待していたのにこのエラーになったのなら、 データベースがその応答を返さなかったことを意味します。

  • bad response length: %d, did the db assert?

    コード: 6

    これは、データベースの応答が 0 未満であることを意味します。 このエラーの原因は、おそらくネットワーク障害かデータベースの破損です。

  • incomplete header

    コード: 7

    めったにありませんが、 データベースの応答が正常にはじまったけれど途中で終わってしまった場合に発生します。 おそらくネットワークの問題でしょう。

  • incomplete response

    コード: 8

    めったにありませんが、 データベースの応答が正常にはじまったけれど途中で終わってしまった場合に発生します。 おそらくネットワークの問題でしょう。

  • couldn't find a response

    コード: 9

    キャッシュされていたレスポンスが見つけられませんでした。

  • error getting socket

    コード: 10

    ソケットが閉じられたか、エラーが発生しました。 ドライバは、(もし可能なら) 次の操作時に自動的に再接続しなければなりません。

  • couldn't find reply, please try again

    コード: 11

    ドライバは、リクエストに直接はマッチしないデータベースからの応答を保存します。 この例外が発生するのは、ドライバがすでにリクエストに対する応答を返した後で、 キャッシュ内に応答を見つけられなかったときです。

  • error getting database response: errstr

    WSA error getting database response: errstr

    "errstr" は、C のソケットから直接返ってきた入出力エラーです。 Windows では、エラーメッセージの先頭に "WSA" がつきます。

  • Timeout error

    コード: 13

    クエリが完了するのを待つ間に何かエラーが発生しました。

  • couldn't send query: <various>

    コード: 14

    送信時に C のソケットエラーが発生しました。

  • max number of retries exhausted, couldn't send query

    Code: 19

    最初の実行が何らかの原因で失敗したときに、ドライバは自動的に 「プレーンな」クエリ (コマンドではないもの) を何度か再送します。 これは、レプリカセットのフェイルオーバー時の例外の発生を減らし (それでも少しは発生しますが)、 一時的なネットワーク障害を取り繕うためです。

    これは、何度実行しても結局データベースに再接続できなかったとき (たとえば、データベースにつながらないときなど) に発生します。

    バージョン 1.2.2 で追加されました。

データベースから渡されたエラー

クエリの実行時に発生したデータベースのエラーは、常に MongoCursorExceptions を発生させなければなりません。 エラーメッセージとエラーコードはデータベースから直接送られるので、 対応するエラーをデータベースのログから見つけることができます。

一般的なデータベースエラーをいくつかまとめました。

  • E11000 duplicate key error index: foo.bar.$X dup key: { /* ... */ }

    コード: 11000

    キーが重複しているときのデータベースエラーです。

  • not master

    コード: 10107, 13435 および 10058

    プライマリではないというエラーで、データベースから送られてきます。 これらのエラーが発生するとドライバは接続を切断し、 新しいプライマリを探します。フェイルオーバーの際に実際に取得するエラーは "not master" ではないかもしれません。 これは、プライマリの変更がいつ発生したのかに依存します。

クラス概要

MongoCursorException
class MongoCursorException extends MongoException {
}

MongoCursorTimeoutException クラス

はじめに

クエリのタイムアウトで発生します。 この例外がスローされるようになるまでの時間の長さを設定することができます。 そのためには、MongoCursor::timeout をカーソルで実行するか、 あるいは MongoCursor::$timeout を設定します。 静的変数を設定する方法は、データベースコマンドや MongoCollection::findOne のようなクエリで便利です。 これらはどちらもカーソルの内部で暗黙的に使うからです。

クラス概要

MongoCursorTimeoutException
class MongoCursorTimeoutException extends MongoCursorException {
}

MongoConnectionException クラス

はじめに

ドライバがデータベースへの接続に失敗した場合にスローします。

エラーメッセージにはさまざまなものがあり、 接続時にどんな問題が発生したのかを調べるために役立ちます。 以下にエラーメッセージの例を示します。

  • No candidate servers found

    MongoDB への接続の確立 (優先読み込みを指定している場合はそれを反映したもの) ができなかった場合に発生します。

  • No server name given.

    このエラーが発生するのは、サーバー名に "" を渡した場合です。 考えられる原因は、文字列中での変数展開用の変数の書き間違い (たとえば "$server" とすべきところを "$servr" にした) などです。

  • failed to get host [hostname] or port [portnum] from [server].

    このエラーがあらわすのは、サーバー文字列が不正な形式であるということです。 "[hostname]" および "[portnum]" の部分が、 ドライバがなんとかそれを判読した結果を示しています。

  • Operation in progress

    データベースへの接続がタイムアウトしました。

  • Transport endpoint is not connected

    一般的には、接続文字列が間違っていて ドライバがデータベースサーバーを見つけられなかったことを意味します。

  • couldn't determine master

    レプリカセット接続の中に、プライマリなサーバーがありません。

  • couldn't get host info for [server]

    これがあらわすのは、指定したサーバーアドレスを DNS が解決できなかったということです。 打ち間違い ("$server" と書くべきところを "server" とするなど) があると容易にこのエラーが発生します。

  • Invalid Argument

    これは、マシン自体は立ち上がっているもののデータベースは稼動していないマシンに接続しようとした場合などに発生します。 接続前に、データベースサーバーが起動しているかどうか確認しておきましょう。

  • Permission denied

    権限に関する問題があってソケットをオープンできなかったことをあらわします。 Red Hat 系の OS のデフォルト設定では Apache からネットワーク接続を作成できないようになっているので、 デフォルトでこれが発生します。この設定を書き換えるには、

    $ /usr/sbin/setsebool -P httpd_can_network_connect 1
    を実行してから Apache を再起動します。

これら以外のメッセージが出た場合、おそらくそれは C のソケットからのエラーです。 主な原因についてはウェブを検索して調べましょう。

クラス概要

MongoConnectionException
class MongoConnectionException extends MongoException {
}

MongoGridFSException クラス

はじめに

データベースのファイルの読み書きでエラーが発生した場合にスローします。

クラス概要

MongoGridFSException
class MongoGridFSException extends MongoException {
}

エラーコード

MongoGridFSException のエラーコード
コード メッセージ 原因
3 Could not open file $filename 無効なファイル、たとえばディレクトリなどを格納しようとしました。
4 File $filename is too large: $filesize bytes GridFS の最大ファイルサイズは 4GB です。
5 could not find filehandle リソースがファイルハンドルを持っていません。
6 no file is associate with this filehandle ファイルリソースではありません。
7 error setting up file: $filenames ファイルを読み込み用にオープンできません。
9 error reading file $filenames ファイルの読み込みに失敗しました。
10 error reading filehandle リソースからの読み込みに失敗しました。
11 could not find uploaded file %s ファイル名が、アップロードされたファイルではないようです。
12 Couldn't find tmp_name in the $_FILES array. Are you sure the upload worked? ファイルのアップロードに失敗したようです。
13 tmp_name was not a string or an array 無効なファイル名が渡されました。
14 couldn't find file size length プロパティがありません。
15 Cannot find filename ファイル名が指定されておらず、filename プロパティも設定されていません。
16 could not open destination file %s 対象ファイルに書き込めません。
17 error reading chunk of file チャンクが壊れています。
18 couldn't create a php_stream ストリームリソースを作れません。
19 couldn't find property チャンクが壊れています。
20 chunk number has wrong size (size) when the max is maxchunksize チャンクが予想より大きすぎます。
21 chunk has wrong format チャンクが壊れています。

The MongoDuplicateKeyException class

はじめに

Thrown when attempting to insert a document into a collection which already contains the same values for the unique keys.

クラス概要

MongoDuplicateKeyException
class MongoDuplicateKeyException extends MongoWriteConcernException {
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 継承したメソッド */
public array MongoWriteConcernException::getDocument ( void )
}

例1 Catching MongoDuplicateKeyException

<?php
$mc 
= new MongoClient("localhost");

$c $mc->selectCollection("test""test");

$c->insert(array('_id' => 1));
try {
    
$c->insert(array('_id' => 1));
} catch (
MongoWriteConcernException $e) {
    echo 
$e->getMessage(), "\n";
}
?>

上の例の出力は、 たとえば以下のようになります。

localhost:27017: insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.test.$_id_  dup key: { : 1 }

The MongoProtocolException class

はじめに

When talking to MongoDB 2.6.0, and later, certain operations (such as writes) may throw MongoProtocolException when the response from the server did not make sense - for example during network failure (we could read the entire response) or data corruption.

This exception is also thrown when attempting to talk newer protocols then the server supports, for example using the MongoWriteBatch when talking to a MongoDB server prior to 2.6.0.

クラス概要

MongoProtocolException
class MongoProtocolException extends MongoException {
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
}

例2 Catching MongoProtocolException

Running the following example against MongoDB prior to 2.6.0 will throw an MongoProtocolException

<?php
$mc 
= new MongoClient("localhost");
$c $mc->selectCollection("test""test");

try {
    
$batch = new MongoInsertBatch($c);
} catch(
MongoProtocolException $e) {
    echo 
$e->getMessage();
}
?>

上の例の出力は、 たとえば以下のようになります。

Current primary does not have a Write API

The MongoExecutionTimeoutException class

はじめに

Thrown when a operation times out server side (i.e. in MongoDB).

To configure the operation timeout threshold, use MongoCursor::maxTimeMS or the "maxTimeMS" command option.

クラス概要

MongoExecutionTimeoutException
class MongoExecutionTimeoutException extends MongoException {
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
}

The MongoWriteConcernException class

はじめに

MongoWriteConcernException is thrown when a write fails. See Write Concerns for how to set failure thresholds.

Prior to MongoDB 2.6.0, the » getLastError command would determine whether a write failed.

クラス概要

MongoWriteConcernException
class MongoWriteConcernException extends MongoCursorException {
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* メソッド */
public array getDocument ( void )
/* 継承したメソッド */
public string MongoCursorException::getHost ( void )
}