[Osaka/Yokohama] Looking for infrastructure/server side engineers!

[Osaka/Yokohama] Looking for infrastructure/server side engineers!

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Successor to CentOS] AlmaLinux OS server construction/migration service

[Successor to CentOS] AlmaLinux OS server construction/migration service

[For WordPress only] Cloud server “Web Speed”

[For WordPress only] Cloud server “Web Speed”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Reservation system development] EDISONE customization development service

[Reservation system development] EDISONE customization development service

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[Global exclusive service] Beyond's MSP in North America and China

[Global exclusive service] Beyond's MSP in North America and China

[YouTube] Beyond official channel “Biyomaru Channel”

[YouTube] Beyond official channel “Biyomaru Channel”

[Laravel] Maximum retries of 10000 reached without finding a unique value ってどういうこと? [Faker]

こんにちは。
開発チームのワイルド担当、まんだいです。

Laravel で開発する際、 seeder でテストデータを作ることになるわけですが、基本同梱されている Faker を使うことが多いと思います。
多言語化もできているし、いろんなテストデータが作成できるので便利なんですが、重複しない ID を持つ複数のデータを作る際に便利な unique というメソッドが用意されていて、これがまた便利なんですよね。

ただ、使い方によっては、タイトルのようなエラーが出ることもあって、どういうことなのか分からない、解消できずに別のやり方で... となると、せっかく Faker を導入したのにもったいない!ってことになるので、今回は、 Faker でよく見る「Maximum retries of 10000 reached without finding a unique value」というエラーの解消方法をご紹介したいと思います。

 

エラーの原因

エラー文言から察するに、どこかの無限ループにハマったなという気はしますが、具体的に心当たりがないことがほとんどで、 Faker の unique() を使っている辺りからエラーが出ていることだけがわかります。
自分では無限ループになるようなコードは書いていないですからね。

適度なタイミングで リセットしてやるとうまく動くのですが、もちろんリセットすると重複が発生します。
このあたりのさじ加減はしばらく使ってみないと分からない部分もありますが、原因が分かれば対処法も自然と分かってくるはず...!!

ということで、Faker の unique() メソッドのコードを追ってみます。

 

unique() の挙動を追う

github のこの部分が unique() メソッドのコードです。
UniqueGenerator というクラスに受け取った変数をそのままパスしているので、更に UniqueGenerator クラスのコードを確認します。

マジックメソッドでうまく挙動を制御していますが、要は UniqueGenerator::__call() でオブジェクトが作られた際に受け取った Faker\Generator オブジェクトのメソッドを呼び出しているだけです。
while の条件式で重複チェックが入っているため、返ってくる値は一意だ、ということです。
配列キーによる重複チェックはかなり原始的な印象ですが、原因としてはわかりやすいですね。
OverflowException がスローされる際のエラーメッセージにタイトルの文言があり、この do while 文のループ回数がリトライ回数に達したというのが原因でした。

 

エラー回避の方法

エラーを回避するための調整項目は一つしかなく、unique() メソッドの第2引数の値を変更し、ループのリトライ回数を引き上げるしかありません。
デフォルトで10000回ですが、欲しい値の数が15000個だと必ずオーバーフローします。

リトライ回数を引き上げるには、以下のようにします。

$factory->define(User::class, function(Faker\Generator $faker) {
    return [
        'name'  => $faker->name(),
        'age' => $faker->unique(false, 15000)->numberBetween(1, 80),    // リトライ回数を 15000 回に変更
    ];
});

 

あと、別の原因として、 Faker\Generator オブジェクトが返す値のバリエーションがそもそも10000個より少ないケースがあります。
上の例もそうですが、そもそも numberBetween() は 1~80 までしか返さないため、81個目のデータはユニークな値が生成できず、リトライ回数を越えてループが実行されます。
人名など、ランダムの組み合わせでバリエーションも豊富な印象ですが、英語のファーストネームは男女合わせて3000程度、ラストネームは473なのでバリエーションはそれなりにありますが、日本語だと名前は男女で50程度しかなく、名字は31、フルネームでも1500程度のバリエーションしかありません。

日本語で5000人分のフルネームが欲しくても、1500通りの組み合わせしかないのであれば、unique() を通しても無意味ということになりますので、何か別の方法を考えなければいけません。
例えば、 Faker\Generator クラスに対して新しいプロバイダーを独自で実装して追加する、という方法があるようですが、まだ詳しく調べきれていないので、いずれご紹介できればと思っています。

 

まとめ

今回は Faker を使っていてちょくちょく見かける「Maximum retries of 10000 reached without finding a unique value」というエラーについて、調べてみました。
事の始まりは、エラーメッセージからネットで調べていると、 StackOverFlow で reset(true) でいいじゃん!みたいな内容を見かけて、全力でおかしいだろうと思ったことがきっかけです。

なにか根本的な勘違いがあるんじゃないかと思って調べてみましたが、落とし穴は一つじゃなかったようです。

「Maximum retries of 10000 reached without finding a unique value」に出くわしたら、リトライ回数と得られるダミーデータの数を調査しよう、ということでした。

 
以上です。

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
1
読み込み中...
1 票, 平均: 1.00 / 11
4,914
X facebook はてなブックマーク pocket
[2024.6.30 CentOS support ended] CentOS server migration solution

[2024.6.30 CentOS support ended] CentOS server migration solution

[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

The person who wrote this article

About the author

Yoichi Bandai

My main job is developing web APIs for social games, but I'm also fortunate to be able to do a lot of other work, including marketing.
Furthermore, my portrait rights in Beyond are treated as CC0 by him.