On connecting to a DB and embedded_migrations::run(&pool.get()?)?;-ing, I get the incredibly unhelpful error "formatter error," which seems to be from deep in std, if the migrations would introduce a constraint violation.
Apply some migrations to prod that worked in dev
[INFO] Started!
[ERROR] Failed with: formatter error
Not from the app/diesel, but from diesel migration run, which shows the error.
have a DB
ALTER TABLE some check constraints on in a migration
run the migration
I'm not sure what exactly are you expecting here.
The steps for reproducing this are quite sparse. (We will need to exact sql that has caused this)
As a blind guess: Maybe something is wrong with the hand written sql?
I'm having the exact same problem trying to run a SQLite migration.
CREATE TABLE `chals` (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
);
This is the full contents of the up.sql in question. Here's some parts of the code:
mod sqlite {
#[derive(EmbedMigrations)]
#[embed_migrations_options(migrations_path = "migrations/sqlite")]
struct _Dummy;
}
...
sqlite::run_with_output(conn, out) // fails
nvm my syntax is wrong, trailing comma
This is a real error that occurs if anything whatsoever goes wrong during a migration run. For example, the following migration:
up.sql
SELECT 1 FROM does_not_exist;
Executed with:
embedded_migrations::run_with_output(&conn, &mut std::io::stdout()).expect("unable to migrate");
Will result in the following output:
Running migration 20190221123919
thread 'main' panicked at 'unable to migrate: MigrationError(IoError(Custom { kind: Other, error: StringError("formatter error") }))', src/libcore/result.rs:997:5
note: Run withRUST_BACKTRACE=1environment variable to display a backtrace.
Executing migration script
What SHOULD be shown is something along the lines of:
thread 'main' panicked at 'unable to migrate: QueryError(DatabaseError(__Unknown, "relation \"does_not_exist\" does not exist"))', src/libcore/result.rs:997:5
It turns out that the reason is very simple. Upon encountering an error, diesel attempts to display the filename of the failed migration:
Since the embedded migration's impl Migration is left without a file_path() implementation:
... it returns the default None, which then triggers the formatting error here:
And since the writeln!() for the error message uses ?, the formatting error from above ends up replacing the original error entirely.
Your explanation of the issue makes sense, but I do not think that pretending an embedded migration has a file path is the right solution. Can we try fixing this by handling the None case in impl Display for MigrationFileName?
Most helpful comment
This is a real error that occurs if anything whatsoever goes wrong during a migration run. For example, the following migration:
up.sql
Executed with:
Will result in the following output:
What SHOULD be shown is something along the lines of:
It turns out that the reason is very simple. Upon encountering an error, diesel attempts to display the filename of the failed migration:
https://github.com/diesel-rs/diesel/blob/03ec1d96ffa8a4f957ba6dc9bd5ab5b556a96d12/diesel_migrations/migrations_internals/src/lib.rs#L337-L344
Since the embedded migration's
impl Migrationis left without afile_path()implementation:https://github.com/diesel-rs/diesel/blob/03ec1d96ffa8a4f957ba6dc9bd5ab5b556a96d12/diesel_migrations/migrations_macros/src/embed_migrations.rs#L37-L49
... it returns the default
None, which then triggers the formatting error here:https://github.com/diesel-rs/diesel/blob/03ec1d96ffa8a4f957ba6dc9bd5ab5b556a96d12/diesel_migrations/migrations_internals/src/migration.rs#L49-L52
And since the
writeln!()for the error message uses?, the formatting error from above ends up replacing the original error entirely.