chenhg5/cc-connect · error

write task script: %w

Error message

write task script: %w

What it means

schtasksManager.Install writes the helper script that the scheduled task will execute (buildWindowsTaskScript(cfg)) to a path under the data dir with os.WriteFile(..., 0600); failure is wrapped as "write task script: %w". This happens after both directories were created successfully, so it usually indicates an ACL/permission or disk problem on the script file itself rather than a missing directory.

Source

Thrown at daemon/windows.go:58

func (*schtasksManager) Platform() string { return "schtasks" }

func (m *schtasksManager) Install(cfg Config) error {
	if err := os.MkdirAll(DefaultDataDir(), 0755); err != nil {
		return fmt.Errorf("create data dir: %w", err)
	}
	if err := os.MkdirAll(filepath.Dir(cfg.LogFile), 0755); err != nil {
		return fmt.Errorf("create log dir: %w", err)
	}

	scriptPath := windowsTaskScriptPath()
	// 0644 has weak semantics on Windows; the file ACL is what matters.
	// We still write 0600 so the file's POSIX bits do not advertise read
	// access, and rely on the user's own profile ACLs for primary defense
	// (the script lives under %USERPROFILE%\.cc-connect by default).
	// WriteFile only applies perm on create, so Chmod the existing file
	// after writing to harden reinstalls of pre-existing 0644 scripts.
	if err := os.WriteFile(scriptPath, []byte(buildWindowsTaskScript(cfg)), 0600); err != nil {
		return fmt.Errorf("write task script: %w", err)
	}
	if err := os.Chmod(scriptPath, 0600); err != nil {
		return fmt.Errorf("chmod task script: %w", err)
	}

	if err := stopWindowsTask(); err != nil {
		slog.Warn("schtasks: stop existing task failed", "error", err)
	}
	if err := deleteWindowsTask(); err != nil {
		if windowsTaskMatchesAction(scriptPath) {
			if err := m.Start(); err != nil {
				return fmt.Errorf("start existing task: %w", err)
			}
			return nil
		}
		return err
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Delete or unlock the existing script file at windowsTaskScriptPath() (under %USERPROFILE%\.cc-connect) and rerun install
  2. Check the wrapped cause: "Access is denied" → fix ACLs or Controlled Folder Access exclusions; "being used by another process" → stop the task/process holding it
  3. Ensure the target volume has free space and is not read-only
  4. If antivirus blocks script creation, add an exclusion for the cc-connect data directory

Example fix

// before
$ cc-connect daemon install
// error: write task script: open ...: Access is denied.
// after
> del %USERPROFILE%\.cc-connect\cc-connect-task.ps1
> cc-connect daemon install
Defensive patterns

Strategy: retry

Validate before calling

scriptPath := filepath.Join(os.Getenv("USERPROFILE"), ".cc-connect", "cc-connect-task.ps1")
if f, err := os.OpenFile(scriptPath, os.O_WRONLY, 0o600); err != nil {
    log.Fatalf("script not writable (%v); delete %s or stop the task holding it open before install", err, scriptPath)
} else {
    f.Close()
}

Try / catch

if err := daemon.Install(cfg); err != nil && strings.Contains(err.Error(), "write task script") {
    time.Sleep(500 * time.Millisecond) // transient lock by running task/AV scan
    if retryErr := daemon.Install(cfg); retryErr != nil {
        return fmt.Errorf("stop the running task or remove the read-only script, then retry: %w", retryErr)
    }
    return nil
}

Prevention

When it happens

Trigger: `cc-connect daemon install` when os.WriteFile on windowsTaskScriptPath() fails: the existing script file is read-only or locked by another process, ACL denies write, the volume is full or read-only, or antivirus blocks writing .ps1/.bat-style scripts.

Common situations: A previous 0644/read-only script left by an old install; an editor or the scheduled task itself holding the script open; Controlled Folder Access (Defender ransomware protection) blocking writes to protected folders; disk quota/full disk.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/8e976d6a5d8659bd. Report an issue: GitHub.