Diesel: formatter error

Created on 2 Feb 2019  路  5Comments  路  Source: diesel-rs/diesel

Setup

Versions

  • Rust: 1.32.0
  • Diesel: 1.4.1
  • Database: Postgres 11
  • Operating System Linux

Feature Flags

  • diesel: chrono, postgres, r2d2, uuid

Problem Description

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.

What are you trying to accomplish?

Apply some migrations to prod that worked in dev

What is the expected output?

[INFO] Started!

What is the actual output?

[ERROR] Failed with: formatter error

Are you seeing any additional errors?

Not from the app/diesel, but from diesel migration run, which shows the error.

Steps to reproduce

have a DB
ALTER TABLE some check constraints on in a migration
run the migration

Checklist

  • [x] I have already looked over the issue tracker for similar issues.
  • [x] This issue can be reproduced on Rust's stable channel. (Your issue will be
    closed if this is not the case)

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

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 with RUST_BACKTRACE=1 environment 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:

https://github.com/diesel-rs/diesel/blob/03ec1d96ffa8a4f957ba6dc9bd5ab5b556a96d12/diesel_migrations/migrations_internals/src/lib.rs#L337-L344

Since the embedded migration's impl Migration is left without a file_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.

All 5 comments

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 with RUST_BACKTRACE=1 environment 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:

https://github.com/diesel-rs/diesel/blob/03ec1d96ffa8a4f957ba6dc9bd5ab5b556a96d12/diesel_migrations/migrations_internals/src/lib.rs#L337-L344

Since the embedded migration's impl Migration is left without a file_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.

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?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gutsle picture gutsle  路  4Comments

kanekv picture kanekv  路  3Comments

killercup picture killercup  路  3Comments

orionz picture orionz  路  3Comments

mkroman picture mkroman  路  3Comments