moonD4rk/HackBrowserData · error

locked copy: %w

Error message

locked copy: %w

What it means

Acquire wraps the copyLocked fallback failure with "locked copy: %w" and joins it with the original "copy: %w" error. This fires only on Windows when BOTH the normal copy failed (file locked by the browser) AND the handle-duplication/file-mapping bypass also failed, meaning the locked file could not be extracted by any available means.

Source

Thrown at filemanager/session.go:54

// On Windows, if the normal copy fails (e.g. file locked by Chrome),
// it falls back to DuplicateHandle + FileMapping to bypass exclusive locks.
func (s *Session) Acquire(src, dst string, isDir bool) error {
	if isDir {
		return copyDir(src, dst, "lock")
	}

	// Try normal copy first
	err := copyFile(src, dst)
	if err != nil {
		// Only attempt locked-file fallback on Windows where Chrome holds exclusive locks.
		// On other platforms, return the original error directly.
		if runtime.GOOS != "windows" {
			return fmt.Errorf("copy: %w", err)
		}
		if err2 := copyLocked(src, dst); err2 != nil {
			return errors.Join(
				fmt.Errorf("copy: %w", err),
				fmt.Errorf("locked copy: %w", err2),
			)
		}
	}

	// Copy SQLite WAL/SHM companion files if present
	var walErrs []error
	for _, suffix := range []string{"-wal", "-shm"} {
		walSrc := src + suffix
		if isFileExists(walSrc) {
			if err := copyFile(walSrc, dst+suffix); err != nil {
				walErrs = append(walErrs, fmt.Errorf("copy %s: %w", suffix, err))
			}
		}
	}
	return errors.Join(walErrs...)
}

// Cleanup removes the session's temporary directory and all its contents.

View on GitHub (pinned to 0503d04d7a)

Solutions

  1. Retry after closing the browser normally — most extraction failures of this kind are transient lock races.
  2. Check that the target file actually exists and a live process holds it (the joined error often includes "no process has file open").
  3. Ensure no EDR/AV policy blocks handle enumeration (NtQuerySystemInformation) for the tool's process.
  4. Free destination disk space — the final write of the recovered content can also fail.

Example fix

// before
if err := s.Acquire(src, dst, false); err != nil {
    return err
}
// after
if err := s.Acquire(src, dst, false); err != nil {
    log.Warnf("acquire %s failed (possibly locked): %v", src, err)
    return fmt.Errorf("acquire %s: %w", src, err) // surface both copy and locked-copy branches
}
Defensive patterns

Strategy: fallback

Validate before calling

// detect a live browser process before relying on the locked-copy fallback
// (fallback needs a process that actually holds the file open)
out, err := exec.Command("tasklist", "/FI", "IMAGENAME eq chrome.exe").Output()
if err != nil || !strings.Contains(strings.ToLower(string(out)), "chrome") {
    log.Warn("chrome not running: locked-copy fallback will fail with 'no process has file open'")
}

Try / catch

// Go: split the joined error to handle each branch
if err := s.Acquire(src, dst, false); err != nil {
    for _, e := range errors.UnwrapMulti(err) { // or iterate joined errors
        log.Warnf("acquire branch failed: %v", e)
    }
    return err
}

Prevention

When it happens

Trigger: Windows-only. Session.Acquire on a file Chrome/Edge holds with exclusive locking_mode where copyFile fails, and copyLocked subsequently fails — e.g. no process currently has the file open (stale lock from a crashed browser), handle enumeration denied, MapFile/ReadFile/Seek failure inside readFileContent, or os.WriteFile to the destination failing.

Common situations: Browser killed uncleanly leaving orphaned locks but no open handles; other instances of the tool or EDR software blocking NtQuerySystemInformation handle enumeration; 32-bit handle-enumeration limitations on large handle tables; destination disk full making the final os.WriteFile fail.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06). Data as JSON: /api/errors/943cdc339a26e4e4. Report an issue: GitHub.