{"record":{"id":"585c05f9573dd8a0","repo":"hasura/graphql-engine","slug":"no-change","errorCode":null,"errorMessage":"no change","messagePattern":"no change","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"cli/migrate/migrate.go","lineNumber":43,"sourceCode":"\t\"github.com/hasura/graphql-engine/cli/v2/migrate/database\"\n\t\"github.com/hasura/graphql-engine/cli/v2/migrate/source\"\n\t\"github.com/hasura/graphql-engine/cli/v2/util\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"golang.org/x/term\"\n)\n\n// DefaultPrefetchMigrations sets the number of migrations to pre-read\n// from the source. This is helpful if the source is remote, but has little\n// effect for a local source (i.e. file system).\n// Please note that this setting has a major impact on the memory usage,\n// since each pre-read migration is buffered in memory. See DefaultBufferSize.\nvar DefaultPrefetchMigrations = uint64(10)\n\n// DefaultLockTimeout sets the max time a database driver has to acquire a lock.\nvar DefaultLockTimeout = 15 * time.Second\n\nvar (\n\tErrNoChange         = errors.New(\"no change\")\n\tErrNilVersion       = errors.New(\"no migration\")\n\tErrLocked           = errors.New(\"database locked\")\n\tErrNoMigrationFiles = errors.New(\"no migration files found\")\n\tErrLockTimeout      = errors.New(\"timeout: can't acquire database lock\")\n\tErrApplied          = errors.New(\"Version already applied in database\")\n\tErrNotApplied       = errors.New(\"Migration not applied in database\")\n\tErrNoMigrationMode  = errors.New(\"Migration mode is disabled\")\n\tErrMigrationMode    = errors.New(\"Migration mode is enabled\")\n)\n\nconst (\n\tapplyingMigrationsMessage = \"Applying migrations\"\n)\n\nfunc newProgressBar(str string, w io.Writer, pbLogs bool) *pb.ProgressBar { //nolint:unparam\n\t// Default behaviour in non-interactive mode\n\tif !pbLogs && !term.IsTerminal(int(os.Stdout.Fd())) {\n\t\treturn nil","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/migrate/migrate.go#L25-L61","documentation":"ErrNoChange is a sentinel error signaling that a migration or metadata operation resulted in no changes (e.g. metadata export identical to stored state). It is informational, not a failure; callers use errors.Is to detect it.","triggerScenarios":"Running Steps() or metadata reload/export flows where the computed state equals the existing state, so nothing was applied or written.","commonSituations":"`hasura migrate apply` with all migrations already applied, or metadata operations producing identical output.","solutions":["Treat it as success/no-op in CLI scripts (compare with errors.Is(err, migrate.ErrNoChange))","No fix needed if no-op behavior is expected","If you expected changes, verify you're pointing at the right endpoint/database"],"exampleFix":"// before\nif err != nil { log.Fatal(err) }\n// after\nif err != nil && !errors.Is(err, migrate.ErrNoChange) { log.Fatal(err) }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func IsNoChange(err error) bool { return errors.Is(err, migrate.ErrNoChange) }","tryCatchPattern":"if err := m.Steps(1); err != nil {\n    if errors.Is(err, migrate.ErrNoChange) { return nil }\n    return err\n}","preventionTips":["Always compare sentinel errors with errors.Is, not string equality","Treat ErrNoChange as a successful no-op in automation"],"tags":["hasura","migration","sentinel","no-op"],"backgroundTag":"no-op-sentinel-error","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}