shadow1ng/fscan · error

%s: %v (LastError: %d) [file_create_failed]

Error message

%s: %v (LastError: %d) [file_create_failed]

What it means

CreateFileW returned INVALID_HANDLE_VALUE, so the dump output file could not be created. The syscall error plus the captured windows.GetLastError() (e.g. 5 access denied, 3 path not found, 80 file exists) are included.

Source

Thrown at plugins/local/minidump.go:530

	createFile, err := pm.kernel32.FindProc("CreateFileW")
	if err != nil {
		return 0, fmt.Errorf("%s: %w", i18n.Tr("minidump_find_proc_failed", "CreateFileW"), err)
	}

	handle, _, callErr := createFile.Call(
		uintptr(unsafe.Pointer(pathPtr)),
		syscall.GENERIC_WRITE,
		0, 0,
		syscall.CREATE_ALWAYS,
		syscall.FILE_ATTRIBUTE_NORMAL,
		0,
	)

	if handle == INVALID_HANDLE_VALUE {
		lastError := windows.GetLastError()
		//nolint:errorlint // Windows LastError不应该wrapped
		return 0, fmt.Errorf(i18n.GetText("file_create_failed")+": %v (LastError: %d)", callErr, lastError)
	}

	return handle, nil
}

// closeHandle 关闭句柄
func (pm *ProcessManager) closeHandle(handle uintptr) {
	if proc, err := pm.kernel32.FindProc("CloseHandle"); err == nil {
		_, _, _ = proc.Call(handle)
	}
}

// isAVBlocking 检测是否有杀软会拦截 LSASS dump
func (p *MiniDumpPlugin) isAVBlocking() bool {
	avProcesses := []string{
		"MsMpEng.exe", "MsSense.exe",
		"CylanceSvc.exe",
		"csfalconservice.exe",

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Choose a writable output path (e.g. %TEMP% or a user-writable directory) and ensure parent directories exist.
  2. Run elevated if writing to protected locations.
  3. Decode the LastError code (5=access denied, 3=path not found, 80=already exists) to pick the right fix.
  4. Delete/rename an existing locked dump file or pick a new filename before retrying.

Example fix

// before
return 0, fmt.Errorf(i18n.GetText("file_create_failed")+": %v (LastError: %d)", callErr, lastError)
// after — validate the destination before calling CreateFileW
if dir := filepath.Dir(path); dir != "." {
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return 0, fmt.Errorf("mkdir %s: %w", dir, err)
	}
}
handle, _, callErr := createFile.Call(...)
Defensive patterns

Strategy: validation

Validate before calling

func validateDumpPath(path string) error {
	if filepath.Ext(path) != ".dmp" {
		return fmt.Errorf("expected .dmp output path, got %q", path)
	}
	dir := filepath.Dir(path)
	if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
		return fmt.Errorf("dump directory %q missing", dir)
	}
	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
	if err != nil {
		return err
	}
	_ = f.Close()
	return nil
}

Type guard

func isInvalidHandle(h uintptr) bool { return h == uintptr(windows.InvalidHandle) || h == 0 }

Try / catch

handle, err := pm.createDumpFile(path)
if err != nil {
	if le := lastErrCode(err); le == 5 { // ERROR_ACCESS_DENIED
		// switch to a writable dir (e.g. %TEMP%) and retry once
	}
	return err
}

Prevention

When it happens

Trigger: createFile.Call(pathPtr, GENERIC_WRITE, 0, 0, ...) yields INVALID_HANDLE_VALUE in createDumpFile — bad output path, read-only directory, or the path is locked by another process.

Common situations: Writing dumps to a protected directory (C:\Windows\System32) without elevation; output path contains invalid characters or points to a nonexistent directory; antivirus quarantining .dmp files; disk full.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/ea4909e8da391b9b. Report an issue: GitHub.