affaan-m/ECC · error

memory connector path is not a directory

Error message

memory connector {name} path is not a directory: {}

What it means

After confirming the directory connector's path is configured, the sync function checks `Path::is_dir` and bails if the path exists but is not a directory (e.g. a regular file). Directory connectors expect a directory to walk (optionally recursively via `recurse`) for .jsonl files.

Solutions

  1. Point the directory connector's path at an actual directory containing .jsonl files.
  2. Use the jsonl_file connector variant instead if a single file was intended.
  3. Create the directory if it does not exist yet, then rerun the sync.

Example fix

// before
[[memory_connectors.jsonl_directory]]
name = "sessions"
path = "/home/user/.ecc/sessions.jsonl"  # wrong: file, not dir
// after
[[memory_connectors.jsonl_directory]]
name = "sessions"
path = "/home/user/.ecc/sessions"  # directory
Defensive patterns

Strategy: validation

Validate before calling

anyhow::ensure!(
    settings.path.is_dir(),
    "directory connector '{}' path is not a directory: {}",
    name,
    settings.path.display()
);

Type guard

fn is_directory(p: &std::path::Path) -> bool {
    p.is_dir()
}

Try / catch

match sync_jsonl_directory(db, name, &settings, limit).await {
    Ok(stats) => stats,
    Err(e) if e.to_string().contains("not a directory") => {
        eprintln!("'{}' expects a directory path; got {}", name, settings.path.display());
        std::process::exit(2);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Configuring a jsonl_directory connector whose `path` points at a regular file, a symlink to a file, or a special file instead of a directory.

Common situations: Copy-pasting a file path into a directory-type connector config, the target path being replaced by a file after config was written, or a misunderstanding between the file and directory connector variants.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/c823380b7f4b42c2. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/main.rs:3126

        limit,
    )?;
    if stats.records_read < limit {
        db.upsert_connector_source_checkpoint(name, &source_path, &signature)?;
    }
    Ok(stats)
}

fn sync_jsonl_directory_memory_connector(
    db: &session::store::StateStore,
    name: &str,
    settings: &config::MemoryConnectorJsonlDirectoryConfig,
    limit: usize,
) -> Result<GraphConnectorSyncStats> {
    if settings.path.as_os_str().is_empty() {
        anyhow::bail!("memory connector {name} has no path configured");
    }
    if !settings.path.is_dir() {
        anyhow::bail!(
            "memory connector {name} path is not a directory: {}",
            settings.path.display()
        );
    }

    let paths = collect_jsonl_paths(&settings.path, settings.recurse)?;
    let default_session_id = settings
        .session_id
        .as_deref()
        .map(|value| resolve_session_id(db, value))
        .transpose()?;

    let mut stats = GraphConnectorSyncStats {
        connector_name: name.to_string(),
        ..Default::default()
    };

    let mut remaining = limit;

View on GitHub (pinned to 8321021c54)