> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Nectr-AI/nectr-ai-pr-review-agent/llms.txt
> Use this file to discover all available pages before exploring further.

# Rescan Repository

> Rebuild the Neo4j code knowledge graph for a connected repository

## Overview

Rescans a connected repository to rebuild its Neo4j code graph. This operation fetches the latest file tree from GitHub and updates the graph database with current repository structure.

Unlike the initial connection scan (which runs in the background), rescan runs **synchronously** and returns the file count immediately.

## Authentication

Requires a valid JWT token in the `Authorization` header.

```
Authorization: Bearer <token>
```

## Path Parameters

<ParamField path="owner" type="string" required>
  Repository owner (user or organization)
</ParamField>

<ParamField path="repo" type="string" required>
  Repository name
</ParamField>

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.nectr.ai/api/v1/repos/acme/my-backend/rescan" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN"
  ```

  ```python Python theme={null}
  import httpx

  headers = {
      "Authorization": "Bearer YOUR_JWT_TOKEN"
  }

  response = httpx.post(
      "https://api.nectr.ai/api/v1/repos/acme/my-backend/rescan",
      headers=headers
  )
  result = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.nectr.ai/api/v1/repos/acme/my-backend/rescan',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_JWT_TOKEN'
      }
    }
  );

  const result = await response.json();
  ```
</CodeGroup>

## Response

<ResponseField name="status" type="string">
  Always returns `"scan_complete"` on success
</ResponseField>

<ResponseField name="repo" type="string">
  Full repository name in `owner/repo` format
</ResponseField>

<ResponseField name="files_indexed" type="integer">
  Number of files successfully indexed in the Neo4j graph
</ResponseField>

### Example Response

```json theme={null}
{
  "status": "scan_complete",
  "repo": "acme/my-backend",
  "files_indexed": 247
}
```

## Graph Rebuild Process

### 1. Fetch Repository Tree

Retrieves the complete file tree from GitHub using the recursive Git tree API:

```http theme={null}
GET https://api.github.com/repos/{owner}/{repo}/git/trees/{default_branch}?recursive=1
```

### 2. Filter Files

Excludes binary and generated directories:

* `node_modules`
* `.git`
* `dist`
* `build`
* `__pycache__`
* `.next`
* `vendor`

### 3. Update Neo4j Graph

**Upsert Repository Node**:

```cypher theme={null}
MERGE (r:Repository {full_name: "owner/repo"})
SET r.scanned_at = "2026-03-10T14:32:10Z"
```

**Upsert File Nodes** (batched in chunks of 200):

```cypher theme={null}
UNWIND $files AS f
MERGE (file:File {repo: $repo, path: f.path})
SET file.language = f.language, file.size = f.size
WITH file
MERGE (r:Repository {full_name: $repo})
MERGE (r)-[:CONTAINS]->(file)
```

**Remove Stale Files**:

```cypher theme={null}
MATCH (r:Repository {full_name: $repo})-[:CONTAINS]->(f:File)
WHERE NOT f.path IN $current_paths
DETACH DELETE f
```

Files deleted from the repository since the last scan are removed from the graph.

### 4. Language Detection

File language is inferred from extension:

| Extension       | Language   |
| --------------- | ---------- |
| `.py`           | Python     |
| `.js`, `.jsx`   | JavaScript |
| `.ts`, `.tsx`   | TypeScript |
| `.java`         | Java       |
| `.go`           | Go         |
| `.rb`           | Ruby       |
| `.rs`           | Rust       |
| `.cpp`, `.c`    | C/C++      |
| `.cs`           | C#         |
| `.php`          | PHP        |
| `.swift`        | Swift      |
| `.kt`           | Kotlin     |
| `.md`           | Markdown   |
| `.yaml`, `.yml` | YAML       |
| `.json`         | JSON       |
| `.sql`          | SQL        |
| `.tf`           | Terraform  |
| *(other)*       | Other      |

## Error Responses

<ResponseField name="401 Unauthorized">
  JWT token is invalid, expired, or missing

  ```json theme={null}
  {
    "detail": "Unauthorized"
  }
  ```
</ResponseField>

<ResponseField name="401 Session Expired">
  GitHub OAuth token cannot be decrypted (SECRET\_KEY changed)

  ```json theme={null}
  {
    "detail": "Session expired — please log out and sign in again."
  }
  ```
</ResponseField>

<ResponseField name="404 Not Found">
  Repository is not connected

  ```json theme={null}
  {
    "detail": "Repo not connected"
  }
  ```
</ResponseField>

<ResponseField name="500 Internal Server Error">
  Rescan operation failed

  ```json theme={null}
  {
    "detail": "GitHub API error fetching file tree: {error}"
  }
  ```

  Or:

  ```json theme={null}
  {
    "detail": "Neo4j write failed: {error}"
  }
  ```

  Or:

  ```json theme={null}
  {
    "detail": "GitHub returned 0 files. Check that your OAuth token has 'repo' scope and that the repository is not empty."
  }
  ```
</ResponseField>

<ResponseField name="503 Service Unavailable">
  Neo4j is not configured on the server

  ```json theme={null}
  {
    "detail": "Neo4j is not configured on this server"
  }
  ```
</ResponseField>

## When to Rescan

Consider rescanning when:

* Major refactoring changed file structure
* Large number of files added/renamed/deleted
* PR reviews seem to lack context on new files
* Initial scan was truncated (large monorepo)
* Repository was migrated or restructured

## Performance Considerations

### Large Repositories

For repositories with >500 MB or >100k files:

* GitHub may truncate the tree API response (logged as warning)
* Scan continues with partial file set
* Consider using a sparse checkout or monorepo tool

### Request Timeout

Rescan is synchronous and may take 10-60 seconds for large repos. Ensure your HTTP client has an appropriate timeout:

```python theme={null}
# Python example
response = httpx.post(
    "https://api.nectr.ai/api/v1/repos/acme/monorepo/rescan",
    headers=headers,
    timeout=120.0  # 2 minutes
)
```

## Graph Consistency

### Preserved Data

Rescan does **not** affect:

* `PullRequest` nodes
* `Developer` nodes
* `Issue` nodes
* Historical `TOUCHES`, `AUTHORED_BY`, `CLOSES` edges

### Updated Data

* `File` nodes (added/updated/removed)
* `Repository.scanned_at` timestamp
* `CONTAINS` edges

## Related Endpoints

* [Connect Repository](/api/repos/connect) - Initial connection triggers background scan
* [List Repositories](/api/repos/list) - View connected repositories
* [Disconnect Repository](/api/repos/disconnect) - Disconnect without deleting graph data
