saola_user_facing_errors/
schema_engine.rs1use serde::Serialize;
2use user_facing_error_macros::*;
3
4#[derive(Debug, UserFacingError, Serialize)]
6#[user_facing(code = "P3000", message = "Failed to create database: {database_error}")]
7pub struct DatabaseCreationFailed {
8 pub database_error: String,
9}
10
11#[derive(Debug, UserFacingError, Serialize)]
14#[user_facing(
15 code = "P3001",
16 message = "Migration possible with destructive changes and possible data loss: {destructive_details}"
17)]
18#[allow(dead_code)]
19pub struct DestructiveMigrationDetected {
20 pub destructive_details: String,
21}
22
23#[derive(Debug, UserFacingError, Serialize)]
25#[user_facing(
26 code = "P3002",
27 message = "The attempted migration was rolled back: {database_error}"
28)]
29#[allow(dead_code)]
30struct MigrationRollback {
31 pub database_error: String,
32}
33
34#[derive(Debug, SimpleUserFacingError)]
36#[user_facing(
37 code = "P3003",
38 message = "The format of migrations changed, the saved migrations are no longer valid. To solve this problem, please follow the steps at: https://pris.ly/d/migrate"
39)]
40#[allow(dead_code)]
41pub struct DatabaseMigrationFormatChanged;
42
43#[derive(Debug, UserFacingError, Serialize)]
44#[user_facing(
45 code = "P3004",
46 message = "The `{database_name}` database is a system database, it should not be altered with prisma migrate. Please connect to another database."
47)]
48pub struct MigrateSystemDatabase {
49 pub database_name: String,
50}
51
52#[derive(Debug, SimpleUserFacingError)]
53#[user_facing(
54 code = "P3005",
55 message = "The database schema is not empty. Read more about how to baseline an existing production database: https://pris.ly/d/migrate-baseline"
56)]
57pub struct DatabaseSchemaNotEmpty;
58
59#[derive(Debug, Serialize)]
60pub struct MigrationDoesNotApplyCleanly {
61 pub migration_name: String,
62 pub inner_error: crate::Error,
63}
64
65impl crate::UserFacingError for MigrationDoesNotApplyCleanly {
66 const ERROR_CODE: &'static str = "P3006";
67
68 fn message(&self) -> String {
69 let error_code = match &self.inner_error.inner {
70 crate::ErrorType::Known(crate::KnownError {
71 message: _,
72 meta: _,
73 error_code,
74 }) => format!("Error code: {}\n", &error_code),
75 crate::ErrorType::Unknown(_) => String::new(),
76 };
77
78 format!(
79 "Migration `{migration_name}` failed to apply cleanly to the shadow database. \n{error_code}Error:\n{inner_error}",
80 migration_name = self.migration_name,
81 inner_error = self.inner_error.message(),
82 error_code = error_code
83 )
84 }
85}
86
87#[derive(Debug, Serialize)]
88pub struct PreviewFeaturesBlocked {
89 pub features: Vec<String>,
90}
91
92impl crate::UserFacingError for PreviewFeaturesBlocked {
93 const ERROR_CODE: &'static str = "P3007";
94
95 fn message(&self) -> String {
96 let blocked: Vec<_> = self.features.iter().map(|s| format!("`{s}`")).collect();
97
98 format!(
99 "Some of the requested preview features are not yet allowed in schema engine. Please remove them from your data model before using migrations. (blocked: {list_of_blocked_features})",
100 list_of_blocked_features = blocked.join(", "),
101 )
102 }
103}
104
105#[derive(Debug, Serialize, UserFacingError)]
106#[user_facing(
107 code = "P3008",
108 message = "The migration `{migration_name}` is already recorded as applied in the database."
109)]
110pub struct MigrationAlreadyApplied {
111 pub migration_name: String,
113}
114
115#[derive(Debug, Serialize, UserFacingError)]
116#[user_facing(
117 code = "P3009",
118 message = "migrate found failed migrations in the target database, new migrations will not be applied. Read more about how to resolve migration issues in a production database: https://pris.ly/d/migrate-resolve\n{details}"
119)]
120pub struct FoundFailedMigrations {
121 pub details: String,
123}
124
125#[derive(Debug, SimpleUserFacingError)]
126#[user_facing(
127 code = "P3010",
128 message = "The name of the migration is too long. It must not be longer than 200 characters (bytes)."
129)]
130pub struct MigrationNameTooLong;
131
132#[derive(Debug, Serialize, UserFacingError)]
133#[user_facing(
134 code = "P3011",
135 message = "Migration `{migration_name}` cannot be rolled back because it was never applied to the database. Hint: did you pass in the whole migration name? (example: \"20201207184859_initial_migration\")"
136)]
137pub struct CannotRollBackUnappliedMigration {
138 pub migration_name: String,
140}
141
142#[derive(Debug, Serialize, UserFacingError)]
143#[user_facing(
144 code = "P3012",
145 message = "Migration `{migration_name}` cannot be rolled back because it is not in a failed state."
146)]
147pub struct CannotRollBackSucceededMigration {
148 pub migration_name: String,
150}
151
152#[derive(Debug, SimpleUserFacingError)]
153#[user_facing(
154 code = "P3013",
155 message = "Datasource provider arrays are no longer supported in migrate. Please change your datasource to use a single provider. Read more at https://pris.ly/multi-provider-deprecation"
156)]
157pub struct DeprecatedProviderArray;
158
159#[derive(Debug, Serialize)]
160pub struct ShadowDbCreationError {
161 pub inner_error: crate::Error,
162}
163
164impl crate::UserFacingError for ShadowDbCreationError {
165 const ERROR_CODE: &'static str = "P3014";
166
167 fn message(&self) -> String {
168 let error_code = match &self.inner_error.inner {
169 crate::ErrorType::Known(crate::KnownError {
170 message: _,
171 meta: _,
172 error_code,
173 }) => format!("Error code: {}\n", &error_code),
174 crate::ErrorType::Unknown(_) => String::new(),
175 };
176
177 format!(
178 "Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at https://pris.ly/d/migrate-shadow\n\nOriginal error: {error_code}\n{inner_error}",
179 inner_error = self.inner_error.message(),
180 error_code = error_code
181 )
182 }
183}
184
185#[derive(Debug, Serialize, UserFacingError)]
186#[user_facing(
187 code = "P3015",
188 message = "Could not find the migration file at {migration_file_path}. Please delete the directory or restore the migration file."
189)]
190pub struct MigrationFileNotFound {
191 pub migration_file_path: String,
192}
193
194#[derive(Debug, Serialize)]
195pub struct SoftResetFailed {
196 pub inner_error: crate::Error,
197}
198
199impl crate::UserFacingError for SoftResetFailed {
200 const ERROR_CODE: &'static str = "P3016";
201
202 fn message(&self) -> String {
203 let error_code = match &self.inner_error.inner {
204 crate::ErrorType::Known(crate::KnownError {
205 message: _,
206 meta: _,
207 error_code,
208 }) => format!("Error code: {}\n", &error_code),
209 crate::ErrorType::Unknown(_) => String::new(),
210 };
211
212 format!(
213 "The fallback method for database resets failed, meaning Migrate could not clean up the database entirely. Original error: {error_code}\n{inner_error}",
214 inner_error = self.inner_error.message(),
215 error_code = error_code
216 )
217 }
218}
219
220#[derive(Debug, Serialize, UserFacingError)]
221#[user_facing(
222 code = "P3017",
223 message = "The migration {migration_name} could not be found. Please make sure that the migration exists, and that you included the whole name of the directory. (example: \"20201207184859_initial_migration\")"
224)]
225pub struct MigrationToMarkAppliedNotFound {
226 pub migration_name: String,
228}
229
230#[derive(Debug, Serialize, UserFacingError)]
231#[user_facing(
232 code = "P3018",
233 message = "A migration failed to apply. New migrations cannot be applied before the error is recovered from. Read more about how to resolve migration issues in a production database: https://pris.ly/d/migrate-resolve\n\nMigration name: {migration_name}\n\nDatabase error code: {database_error_code}\n\nDatabase error:\n{database_error}
234"
235)]
236pub struct ApplyMigrationError {
237 pub migration_name: String,
238 pub database_error_code: String,
239 pub database_error: String,
240}
241
242#[derive(Debug, Serialize)]
243pub struct ProviderSwitchedError {
244 pub provider: String,
246 pub expected_provider: String,
248}
249
250impl crate::UserFacingError for ProviderSwitchedError {
251 const ERROR_CODE: &'static str = "P3019";
252
253 fn message(&self) -> String {
254 let provider = &self.provider;
255 let expected_provider = &self.expected_provider;
256
257 match (provider.as_str(), expected_provider.as_str()) {
258 ("cockroachdb", "postgresql") => format!(
259 "The datasource provider `{provider}` specified in your schema does not match the one specified in the migration_lock.toml, `{expected_provider}`. Check out the following documentation for how to resolve this: https://pris.ly/d/cockroachdb-postgresql-provider"
260 ),
261 _ => format!(
262 "The datasource provider `{provider}` specified in your schema does not match the one specified in the migration_lock.toml, `{expected_provider}`. Please remove your current migration directory and start a new migration history with prisma migrate dev. Read more: https://pris.ly/d/migrate-provider-switch"
263 ),
264 }
265 }
266}
267
268#[derive(Debug, SimpleUserFacingError)]
269#[user_facing(
270 code = "P3020",
271 message = "The automatic creation of shadow databases is disabled on Azure SQL. Please set up a shadow database using the `shadowDatabaseUrl` datasource attribute.\nRead the docs page for more details: https://pris.ly/d/migrate-shadow"
272)]
273pub struct AzureMssqlShadowDb;
274
275#[derive(Debug, SimpleUserFacingError)]
276#[user_facing(
277 code = "P3021",
278 message = "Foreign keys cannot be created on this database. Learn more how to handle this: https://pris.ly/d/migrate-no-foreign-keys"
279)]
280pub struct ForeignKeyCreationNotAllowed;
281
282#[derive(Debug, SimpleUserFacingError)]
283#[user_facing(
284 code = "P3022",
285 message = "Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database. Please read more here about how to handle this: https://pris.ly/d/migrate-no-direct-ddl"
286)]
287pub struct DirectDdlNotAllowed;
288
289#[derive(Debug, SimpleUserFacingError)]
290#[user_facing(
291 code = "P3023",
292 message = "For the current database, `externalTables` & `externalEnums` in your prisma config must contain only fully qualified identifiers (e.g. `schema_name.table_name`)."
293)]
294pub struct MissingNamespaceInExternalTables;
295
296#[derive(Debug, SimpleUserFacingError)]
297#[user_facing(
298 code = "P3024",
299 message = "For the current database, `externalTables` & `externalEnums` in your prisma config must contain only simple identifiers without a schema name."
300)]
301pub struct UnexpectedNamespaceInExternalTables;
302
303#[derive(Debug, SimpleUserFacingError)]
304#[user_facing(code = "P4001", message = "The introspected database was empty.")]
305pub struct IntrospectionResultEmpty;
306
307#[derive(Debug, UserFacingError, Serialize)]
308#[user_facing(
309 code = "P4002",
310 message = "The schema of the introspected database was inconsistent: {explanation}"
311)]
312pub struct DatabaseSchemaInconsistent {
313 pub explanation: String,
315}
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320 use crate::UserFacingError;
321
322 #[test]
323 fn test_user_facing_error_impl_for_database_creation_failed() {
324 assert_eq!(DatabaseCreationFailed::ERROR_CODE, "P3000");
325
326 let error = DatabaseCreationFailed {
327 database_error: "oops".to_string(),
328 };
329
330 assert_eq!(error.message(), "Failed to create database: oops")
331 }
332}