The dialog title microsoft sql server management studio an error occurred when attaching the database s tells you SSMS failed to complete an ATTACH_DB operation on a file named something like database.mdf, and the message column holds the actual error number. Click the hyperlink in the message column to read the real cause, because the popup itself only says the attach failed. That single click usually distinguishes a permissions problem from a corrupt log file or a version mismatch in under 30 seconds.

Mechanism: How an Attach Request Fails

When you attach a database, SSMS never touches the files itself. It sends a CREATE DATABASE statement with a FOR ATTACH clause (or FOR ATTACH_REBUILD_LOG) to the SQL Server engine, and the engine does the work. SSMS is a client wrapper that renders the result as a modal dialog. The popup therefore mirrors whatever the engine returned, and the hyperlink exposes the extended error text the grid truncated.

The engine performs four sequential checks, and the first one that fails aborts the attach. It first resolves the physical path against the service account's token, not yours. It then validates the file header against the running engine build, then verifies that the transaction log chain matches the data file, and finally acquires an exclusive lock and registers the database in sys.databases.

Every failure surfaces as the same outer message but a different inner code. A sharing violation (error 32) means another process holds the file. Access denied (error 5) means the NT SERVICE\MSSQLSERVER account lacks NTFS rights. Error 5120 wraps a generic access failure. Error 1813 means the log cannot be rebuilt. Error 945 means the log is unreadable. The popup hides all of this behind a hyperlink because the grid column is fixed-width.

That is the counterintuitive part: SSMS is almost never the cause. The dialog is a reporting layer, so reinstalling SSMS or restarting the GUI changes nothing. The defect lives in file ACLs, engine build numbers, or log chain consistency, and diagnosing it requires reading the extended error rather than the outer message.

Quantified Context: Error Numbers and Build Thresholds

The extended message almost always contains a numeric code, and the code narrows the cause faster than any guesswork. Error 5120 accounts for most attachment failures on restored or copied files, because copied files routinely lose inherited ACLs. Errors 1813 and 945 point at log problems rather than permission problems, and mixing the two wastes hours.

Version mismatch is the second largest bucket. A data file's internal version must be less than or equal to the engine's, and a 2019 engine (internal version 904) cannot open a file last touched by a 2022 engine (internal 957). Compatibility level is a separate number and is irrelevant to attachment. You can check both in seconds: SELECT SERVERPROPERTY('ProductVersion'), and a build such as 16.0.1000.6 maps to SQL Server 2022.

Permissions failures cluster around three accounts. The engine runs as NT SERVICE\MSSQLSERVER by default, a named instance uses NT SERVICE\MSSQL$InstanceName, and SQL Server Express uses the same NT SERVICE pattern. The user who clicks OK in SSMS is not one of them. A file readable by your admin account can still be unreadable by the engine, and that gap explains most error 5 and 5120 reports.

A useful threshold: if the error number is 5120, 5, or 32, suspect permissions and file locks before anything else. If it is 1813 or 945, suspect the log. If it mentions version numbers or "downgrade," the file came from a newer engine than the one you are attaching to.

Timeline: Attach Operation Sequence

Stage Engine action Typical failure Error code
1. Path resolution Validates the literal path exists Typo or missing drive letter 5120
2. Token check Opens the file under the service SID ACL denies service account 5, 5120
3. Lock acquisition Requests exclusive open Another process or instance holds it 32
4. Header validation Reads the file header version Newer build than engine 946
5. Log validation Matches LSN chain to data file Missing or stale log 945
6. Log rebuild (if requested) Rebuilds log under FOR ATTACH_REBUILD_LOG Data file not cleanly shut down 1813
7. Registration Writes entry to sys.databases Name collision or metadata conflict 5173

The sequence matters because a failure at stage 2 prevents the engine from ever reaching stage 4. Reading the error code tells you which stage aborted, and therefore which check to investigate. A stage 2 failure and a stage 5 failure produce identical popups but need opposite fixes.

Edge Cases: Restored Files, Copies, and Express Instances

A database file copied from another server carries the source machine's SID history in its ACL, and the copy operation may strip inherited entries entirely. The engine then cannot open a file that its own service account created on the original host. This is the single most common reason a file works on server A and fails on server B with error 5120.

A missing transaction log is another distinct case. If you attach only the .mdf and request FOR ATTACH_REBUILD_LOG, the engine rebuilds the log, but that path requires the data file to be cleanly shut down. A file copied while the source was running, or after an abrupt shutdown, fails with error 1813 because the engine cannot guarantee consistency. In that situation, attach the original log rather than rebuilding.

SQL Server Express adds a wrinkle: it enforces a 10 GB per-database limit. Attaching an oversized file to Express fails with its own error rather than a permission code, so check the edition before chasing ACLs. Named instances and multiple instances also compete for exclusive locks, and two engines pointing at the same file produce error 32 even when permissions are flawless.

A 64-bit versus 32-bit mismatch, or a file from a different platform build (Linux versus Windows), can also block attachment. The header validation step catches these but reports them as version or build errors rather than as platform errors.

Sharing violation (32): another process, another instance, or a stale handle still holds the file; stop the owning service before retrying. Access denied (5 or 5120): grant the service SID full control on the folder, not just the file, because the engine also needs log and container files. Log rebuild failure (1813): the data file was not cleanly shut down; attach the real log or accept that the rebuild cannot proceed. Version downgrade (946): the file came from a newer engine build; attach it to that build or later, never earlier. Name collision (5173): a database with the same logical name already exists in sys.databases; detach or rename before retrying.

Misconceptions: What Does Not Cause the Error

The popup is not an SSMS bug. Reinstalling Management Studio, running it as administrator, or switching to Azure Data Studio changes nothing, because the failure happens inside the engine process and SSMS merely displays the result. Elevating the GUI does not elevate the engine's service token.

Running the SSMS GUI as administrator is a common but ineffective workaround. The service account still opens the file, and the GUI's elevation is irrelevant to that token. What actually helps is granting NTFS rights to the service SID or changing the service account to one that already has access.

Another misconception: compatibility level governs attachment. It does not. Compatibility level affects query optimizer behavior, while attachment depends on the internal database version, which is tied to engine build. A database at compatibility 150 can live on a 2019 engine, and a 2022-era file cannot attach to a 2019 engine regardless of its compatibility setting.

A third: the log is optional. FOR ATTACH_REBUILD_LOG exists, but it only works when the data file is cleanly shut down, and the engine will refuse with 1813 otherwise. Treating the log as disposable leads directly to that error.

A professional caveat: error numbers from the extended message are authoritative, but the outer popup text is generic by design. Teams that log only the outer message lose the diagnostic payload, so configure SSMS or the ERRORLOG to capture the full extended text. The hyperlink is not decorative; it is the entire diagnosis.

Comparison: Attach, Detach, and Restore Paths

Method Log required Version rule Best for Main failure mode
ATTACH (existing log) Yes, matching LSN chain File version ≤ engine Moving a cleanly shut-down pair 5120 or 945
ATTACH_REBUILD_LOG No, rebuilt File version ≤ engine Clean .mdf without log 1813 on dirty files
DETACH then copy Yes at source None until reattach Planned server migration Locks and ACL loss
RESTORE from backup No, regenerated Same or newer engine Disaster recovery Backup chain gaps
Import/Export wizard No Not applicable Selective data movement Schema drift
Backup/copy via detach Yes File version ≤ engine Controlled moves Error 32 if source still running

The table makes the tradeoff explicit: paths that skip the log (restore, rebuild) trade log consistency for convenience, and each has a failure mode that the extended error names. Restore is the safest for version mismatches because the backup format is more portable than the raw file.

Practical Actions: Fixing the Attach Failure

Read the hyperlink first. Open the extended message, note the numeric error, and classify it as permission (5, 32, 5120), log (945, 1813), or version (946, downgrade text). That classification determines every subsequent step, and skipping it is why many attach attempts loop.

For permission failures, grant the service SID full control on the containing folder, not just the .mdf. Use icacls against NT SERVICE\MSSQLSERVER or the named-instance equivalent, and include the .ldf and any secondary files. Then retry the attach without restarting the engine.

For sharing violations, identify the holder. Stop the competing instance, close any file handle from a copy operation, and confirm the service account is the only opener. Error 32 rarely survives a clean service stop and a retry.

For log problems, attach the matching log pair if you have it. If you must use FOR ATTACH_REBUILD_LOG, verify the data file was cleanly shut down, and expect 1813 when it was not. For version downgrades, attach to the newer engine build and script the objects out rather than forcing a downlevel attach.

For repeated failures, capture the full extended error in the ERRORLOG and SSMS output. One reliable signal beats ten guesses, and the error number is the only durable clue the engine gives you.

Limitations: When the Popup Cannot Tell You Enough

The dialog reports the engine's first failure only. If multiple conditions are wrong, such as a missing log and an ACL denial, fixing the first may reveal the second on the next attempt, so a single popup never rules out other problems. Treat each retry as a fresh diagnostic round.

The extended error is also build-specific. Microsoft changes message text and error codes across service packs and cumulative updates, so a code that meant one thing on an older build may carry a different nuance on a newer one. The error number is more stable than the message wording.

Finally, nothing in this article substitutes for testing against your own engine build and file lineage. Version numbers, ACL behavior, and Express limits vary by edition and patch level, and the only authoritative confirmation is a controlled attach attempt on the target instance with the full error captured.