Skip to content

Fix auto-link not updating BibEntry when associated files are found (#15084)#15124

Open
shubh1978 wants to merge 39 commits intoJabRef:mainfrom
shubh1978:fix/autolink-replace-broken-linkedfile
Open

Fix auto-link not updating BibEntry when associated files are found (#15084)#15124
shubh1978 wants to merge 39 commits intoJabRef:mainfrom
shubh1978:fix/autolink-replace-broken-linkedfile

Conversation

@shubh1978
Copy link

@shubh1978 shubh1978 commented Feb 16, 2026

Closes #15084

PR Description

We fixed an issue where auto-linking files did not update the BibEntry file list when associated files were found.

Previously, the file finder correctly detected matching files but the BibEntry file field was not updated properly, causing the UI and saved library to not reflect the linked files. This fix ensures that linked files are correctly added or updated in the BibEntry so the UI and persistence layer reflect the changes.

Steps to test

  1. Open JabRef
  2. Open the test file:
    test-support/src/manual-tests/issue-9798/example1/issue-9798_1.bib
  3. Run:
    Quality → Automatically set file links
  4. Observe:
    • Linked files are detected
    • BibEntry file field updates
    • UI reflects linked file correctly

Proof of issue being fixed

image

Verification screenshot (required by contribution guidelines)

Library with a single entry having author as myself and title as the issue number (#15084):

image

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef
  • I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • [/] I described the change in CHANGELOG.md
  • [/] I checked the user documentation

@github-actions
Copy link
Contributor

Hey @shubh1978! 👋

Thank you for contributing to JabRef!

We have automated checks in place, based on which you will soon get feedback if any of them are failing. We also use Qodo for review assistance. It will update your pull request description with a review help and offer suggestions to improve the pull request.

After all automated checks pass, a maintainer will also review your contribution. Once that happens, you can go through their comments in the "Files changed" tab and act on them, or reply to the conversation if you have further inputs. You can read about the whole pull request process in our contribution guide.

Please ensure that your pull request is in line with our AI Usage Policy and make necessary disclosures.

@qodo-free-for-open-source-projects
Copy link
Contributor

Review Summary by Qodo

Fix auto-link not updating BibEntry when associated files found

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fixed auto-link not updating BibEntry file list when associated files found
• Ensured LinkedFile objects are updated instead of replaced during repair
• Added explicit file field update mechanism in UI thread execution
• Improved file discovery logic to properly handle directory traversal
• Added fallback AutoLinkPreferences initialization for robustness
Diagram
flowchart LR
  A["Auto-link Action"] -->|"Execute with preferences"| B["AutoSetFileLinksUtil"]
  B -->|"Find associated files"| C["File Discovery"]
  C -->|"Match files by citation key"| D["LinkedFile Objects"]
  D -->|"Update or replace existing"| E["BibEntry File List"]
  E -->|"Set field + notify UI"| F["UI Update"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java 🐞 Bug fix +48/-12

Enhanced file update mechanism with explicit field setting

• Added import for AutoLinkPreferences
• Added fallback initialization of AutoLinkPreferences when null
• Refactored onLinkedFilesUpdated lambda with improved formatting
• Added explicit entry.setField() call to update FILE field in addition to setFiles()
• Added debug logging for file field updates

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java


2. jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java 🐞 Bug fix +197/-60

Refactored file linking logic with proper object updates

• Modified constructor to discover additional directories by walking database parent path
• Added null-safety checks for autoLinkPreferences with fallback defaults
• Refactored doLinkAssociatedFiles() to replace broken LinkedFile objects instead of creating new
 lists
• Changed logic to update existing files and add new ones in single pass
• Rewrote findAssociatedNotLinkedFilesWithFinder() with direct file system traversal
• Fixed buildLinkedFileFromPath() to use relative paths from base directory
• Simplified findAssociatedNotLinkedFilesWithUniqueName() using putIfAbsent()
• Added extensive debug logging throughout file discovery and update process

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java


3. CHANGELOG.md 📝 Documentation +1/-1

Document auto-link BibEntry update fix

• Added entry documenting fix for auto-link file list update issue #15084

CHANGELOG.md


Grey Divider

Qodo Logo

@testlens-app
Copy link

testlens-app bot commented Feb 16, 2026

✅ All tests passed ✅

🏷️ Commit: fbf5207
▶️ Tests: 11192 executed
⚪️ Checks: 59/59 completed


Learn more about TestLens at testlens.app.

@qodo-free-for-open-source-projects
Copy link
Contributor

qodo-free-for-open-source-projects bot commented Feb 16, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (4) 📎 Requirement gaps (0)

Grey Divider


Action required

✅ 1. System.out.println debug logs 📘 Rule violation ⛨ Security
Description
New code writes unstructured debug output to stdout and includes file paths/citation keys, which can
leak sensitive user/library information and is not compliant with secure logging practices. Replace
these statements with the project logger (or remove them) and avoid logging sensitive values.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R332-335]

+                        System.out.println("DEBUG citationKey = " + citationKey);
+                        System.out.println("DEBUG found file = " + path);
+                        System.out.println("DEBUG basename = " + FileUtil.getBaseName(path));
+
Evidence
The checklist requires secure logging practices (no sensitive data, structured logs). The PR adds
multiple System.out.println debug statements that print potentially sensitive values such as
citation keys and filesystem paths, and they are not structured or controlled by log levels.

Rule 5: Generic: Secure Logging Practices
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[332-335]
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[106-108]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New code uses `System.out.println(...)` for debugging and prints potentially sensitive information (citation keys, filesystem paths). This violates secure logging expectations and bypasses log levels/formatting.
## Issue Context
JabRef should use its logging framework (e.g., `LOGGER.debug/info/warn/error`) and avoid emitting sensitive data in logs. Stdout prints are also typically disallowed by style/lint checks.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[158-159]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[181-182]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[204-206]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[214-216]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[332-335]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[381-383]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[67-68]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[106-108]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. Broad catch (Exception e) 📘 Rule violation ⛯ Reliability
Description
The new catch (Exception e) is overly broad and silently degrades behavior by swallowing the
exception without logging context. This makes failures harder to diagnose and violates the
requirement for specific, properly-logged exception handling.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R369-379]

+        try {
+
+            Path baseDir = directories.get(0);
+
+            relativePath = baseDir.relativize(associatedFile);
+
+        } catch (Exception e) {
+
+            relativePath = associatedFile;
+
+        }
Evidence
The checklist prohibits introducing overly broad exception handling and requires proper exception
logging. The PR adds a catch (Exception e) that does not log the exception and instead silently
falls back to using the absolute path.

AGENTS.md
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[369-379]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`buildLinkedFileFromPath` introduces `catch (Exception e)` and swallows it without logging. This is overly broad and hides real failures.
## Issue Context
The method uses `directories.get(0)` and `Path.relativize`, both of which can fail for specific reasons. Compliance requires catching specific exceptions and logging them properly (exception object passed as the last argument).
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[369-379]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Recursive directory explosion 🐞 Bug ➹ Performance
Description
The AutoSetFileLinksUtil constructor now walks the database parent directory and adds every
subdirectory, which can be huge and redundant. This runs on the JavaFX/UI thread in the menu action
and can severely degrade performance when combined with recursive file searching.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R71-87]

+        List<Path> dirs = new ArrayList<>(databaseContext.getFileDirectories(filePreferences));
+
+        databaseContext.getDatabasePath().ifPresent(dbPath -> {
+            Path parent = dbPath.getParent();
+            if (parent != null) {
+                try (Stream<Path> walk = Files.walk(parent)) {
+                    walk.filter(Files::isDirectory)
+                        .forEach(dir -> {
+                            if (!dirs.contains(dir)) {
+                                dirs.add(dir);
+                            }
+                        });
+                } catch (IOException e) {
+                    LOGGER.error("Error walking directories", e);
+                }
+            }
+        });
Evidence
The constructor performs an unbounded Files.walk(parent) and collects all directories. In
AutoLinkFilesAction.execute, this constructor is called before the background task starts, so the
walk happens on the UI thread. Additionally, the existing finder already does deep recursive
traversal of each configured directory, so adding all subdirectories multiplies work.

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[66-112]
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[52-76]
jablib/src/main/java/org/jabref/logic/util/io/CitationKeyBasedFileFinder.java[74-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AutoSetFileLinksUtil` constructor currently walks the entire database parent tree and adds every subdirectory as a search root. This can be extremely slow and redundant, and in `AutoLinkFilesAction.execute` it happens on the JavaFX/UI thread.
### Issue Context
Existing `FileFinder` implementations already recurse within each configured directory root (e.g., `Files.find(..., Integer.MAX_VALUE, ...)`). Adding all subdirectories as additional roots multiplies traversal work.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[66-112]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[52-76]
- jablib/src/main/java/org/jabref/logic/util/io/CitationKeyBasedFileFinder.java[74-92]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. Overwrites valid file links 🐞 Bug ✓ Correctness
Description
Auto-link now replaces existing linked files purely by basename match, without checking whether the
existing link is broken or ensuring correct matching rules. This can overwrite a valid user-selected
link when another file with the same basename is found.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R168-191]

+        for (LinkedFile existing : currentFiles) {
+
+            Optional<LinkedFile> replacement =
+                    foundFiles.values().stream()
+                              .filter(newFile ->
+                                      FileUtil.getBaseName(newFile.getLink())
+                                              .equals(FileUtil.getBaseName(existing.getLink())))
+                              .findFirst();
+
+            if (replacement.isPresent()) {
+
+                LinkedFile newFile = replacement.get();
+
+                System.out.println("DEBUG: REPLACING FILE → " + existing.getLink());
+
+                updatedFiles.add(newFile);
+
+                updated = true;
+
+            } else {
+
+                updatedFiles.add(existing);
+
+            }
Evidence
The replacement loop uses basename equality and replaces the LinkedFile object unconditionally.
Repository logic and tests indicate broken-link-name matching should only apply to broken links, and
previous code contains explicit broken-link and extension checks.

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[149-225]
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[234-258]
jablib/src/main/java/org/jabref/logic/util/io/BrokenLinkedFileNameBasedFileFinder.java[59-64]
jabgui/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java[633-660]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`doLinkAssociatedFiles` currently replaces existing linked files based solely on basename matching, without checking if the existing link is broken. This can overwrite correct user links and violates the intended broken-link repair behavior.
### Issue Context
The codebase contains explicit broken-link-only behavior (`BrokenLinkedFileNameBasedFileFinder`) and repair logic with extension matching (`autoLinkBrokenLinkedFiles`). Unit tests expect that copies do not trigger relinking.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[149-225]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[234-258]
- jablib/src/main/java/org/jabref/logic/util/io/BrokenLinkedFileNameBasedFileFinder.java[59-64]
- jabgui/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java[633-660]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Bad path relativization 🐞 Bug ✓ Correctness
Description
Auto-linked files now compute relative paths using directories.get(0).relativize(...), which may
be unrelated to the found file’s actual base directory. This can produce incorrect relative paths or
fall back to absolute paths, harming portability and link resolution.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R363-387]

+
+        String fileType = checkAndGetFileType(associatedFile);
+
+        // CRITICAL FIX: use RELATIVE TO DATABASE DIRECTORY ONLY
+        Path relativePath;
+
+        try {
+
+            Path baseDir = directories.get(0);
+
+            relativePath = baseDir.relativize(associatedFile);
+
+        } catch (Exception e) {
+
+            relativePath = associatedFile;
+
+        }
+
+        System.out.println("DEBUG RELATIVE PATH = " + relativePath);
+
+        return new LinkedFile(
+                "",
+                relativePath,
+                fileType
+        );
Evidence
The repo already provides FileUtil.relativize(file, directories) which selects the correct prefix
directory (and can use real paths). BibDatabaseContext.getFileDirectories returns an ordered list
where index 0 may be user-/library-specific, not necessarily the directory that contains the file;
hard-coding index 0 is incorrect.

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[362-388]
jablib/src/main/java/org/jabref/logic/util/io/FileUtil.java[287-317]
jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java[147-196]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`buildLinkedFileFromPath` now relativizes against `directories.get(0)` which is not guaranteed to be the correct base directory. This can generate incorrect relative paths or absolute paths.
### Issue Context
`FileUtil.relativize` already implements correct selection of the base directory by checking prefixes (and real paths). `BibDatabaseContext.getFileDirectories` order can put user/library metadata directories first.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[362-388]
- jablib/src/main/java/org/jabref/logic/util/io/FileUtil.java[287-317]
- jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java[147-196]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

✅ 6. Unused finder parameter 📘 Rule violation ✓ Correctness
Description
The updated implementation no longer uses the finder parameter in
findAssociatedNotLinkedFilesWithFinder, which can trigger lint/checkstyle failures and makes the
API misleading. Either use finder as intended or remove it (and update callers/tests accordingly).
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R315-355]

+        List<LinkedFile> result = new ArrayList<>();
+
+        Optional<String> citationKeyOpt = entry.getCitationKey();
+
+        if (citationKeyOpt.isEmpty()) {
+            return result;
+        }
+
+        String citationKey = citationKeyOpt.get();
+
+        for (Path dir : directories) {
+
+            try (Stream<Path> walk = Files.walk(dir)) {
+
+                walk.filter(Files::isRegularFile)
+                    .forEach(path -> {
+
+                        System.out.println("DEBUG citationKey = " + citationKey);
+                        System.out.println("DEBUG found file = " + path);
+                        System.out.println("DEBUG basename = " + FileUtil.getBaseName(path));
+
+                        Optional<String> ext = FileUtil.getFileExtension(path);
+
+                        if (ext.isEmpty()) return;
+
+                        if (!extensions.contains(ext.get())) return;
-        // Only keep associated files that are not linked
-        return associatedFiles
-                .stream()
-                .filter(associatedFile -> !isFileAlreadyLinked(associatedFile, linkedFiles))
-                .map(this::buildLinkedFileFromPath)
-                .toList();
+                        String fileName = FileUtil.getBaseName(path);
+
+                        if (citationKey.equals(fileName)) {
+
+                            System.out.println("MATCH FOUND");
+
+                            result.add(buildLinkedFileFromPath(path));
+                        }
+                    });
+
+            }
+        }
+
+        return result;
Evidence
The checklist requires changes not to introduce issues that would fail JabRef linting/modernization
checks. The PR replaces the body of findAssociatedNotLinkedFilesWithFinder with a manual
Files.walk search that does not use the finder parameter at all, which commonly violates
unused-parameter checks and makes the method contract misleading.

AGENTS.md
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[315-355]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`findAssociatedNotLinkedFilesWithFinder(BibEntry entry, FileFinder finder, ...)` no longer uses `finder`, which can fail linting and makes the method misleading.
## Issue Context
The method name and signature imply that `finder` drives the associated file search, but the new implementation performs its own filesystem walk instead.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[224-355]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 7. File-search logic in GUI 📘 Rule violation ⛯ Reliability
Description
The PR adds substantial filesystem traversal and matching logic (Files.walk over directories and
DB parent) inside the GUI package, increasing coupling of GUI to non-UI logic. This should be moved
to org.jabref.logic (or an existing logic-layer service) with the GUI acting as a thin
orchestrator.
Code

jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[R71-87]

+        List<Path> dirs = new ArrayList<>(databaseContext.getFileDirectories(filePreferences));
+
+        databaseContext.getDatabasePath().ifPresent(dbPath -> {
+            Path parent = dbPath.getParent();
+            if (parent != null) {
+                try (Stream<Path> walk = Files.walk(parent)) {
+                    walk.filter(Files::isDirectory)
+                        .forEach(dir -> {
+                            if (!dirs.contains(dir)) {
+                                dirs.add(dir);
+                            }
+                        });
+                } catch (IOException e) {
+                    LOGGER.error("Error walking directories", e);
+                }
+            }
+        });
Evidence
The checklist requires GUI code to delegate complex non-UI operations to the logic layer. The PR
adds recursive directory walking and associated-file matching logic in
org.jabref.gui.externalfiles, which is GUI-layer code performing substantial non-UI work.

AGENTS.md
jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[71-87]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Complex filesystem traversal and matching logic was added/expanded in the GUI layer (`org.jabref.gui...`). Per layering rules, this kind of logic should live in `org.jabref.logic` with GUI as the gateway.
## Issue Context
The changes include recursive directory walking and manual file matching which are not UI concerns and increase coupling/testing difficulty.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[71-87]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[315-355]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 332 to 335
System.out.println("DEBUG citationKey = " + citationKey);
System.out.println("DEBUG found file = " + path);
System.out.println("DEBUG basename = " + FileUtil.getBaseName(path));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. system.out.println debug logs 📘 Rule violation ⛨ Security

New code writes unstructured debug output to stdout and includes file paths/citation keys, which can
leak sensitive user/library information and is not compliant with secure logging practices. Replace
these statements with the project logger (or remove them) and avoid logging sensitive values.
Agent Prompt
## Issue description
New code uses `System.out.println(...)` for debugging and prints potentially sensitive information (citation keys, filesystem paths). This violates secure logging expectations and bypasses log levels/formatting.

## Issue Context
JabRef should use its logging framework (e.g., `LOGGER.debug/info/warn/error`) and avoid emitting sensitive data in logs. Stdout prints are also typically disallowed by style/lint checks.

## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[158-159]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[181-182]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[204-206]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[214-216]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[332-335]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[381-383]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[67-68]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[106-108]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 369 to 379
try {

Path baseDir = directories.get(0);

relativePath = baseDir.relativize(associatedFile);

} catch (Exception e) {

relativePath = associatedFile;

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Broad catch (exception e) 📘 Rule violation ⛯ Reliability

The new catch (Exception e) is overly broad and silently degrades behavior by swallowing the
exception without logging context. This makes failures harder to diagnose and violates the
requirement for specific, properly-logged exception handling.
Agent Prompt
## Issue description
`buildLinkedFileFromPath` introduces `catch (Exception e)` and swallows it without logging. This is overly broad and hides real failures.

## Issue Context
The method uses `directories.get(0)` and `Path.relativize`, both of which can fail for specific reasons. Compliance requires catching specific exceptions and logging them properly (exception object passed as the last argument).

## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[369-379]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 71 to 87
List<Path> dirs = new ArrayList<>(databaseContext.getFileDirectories(filePreferences));

databaseContext.getDatabasePath().ifPresent(dbPath -> {
Path parent = dbPath.getParent();
if (parent != null) {
try (Stream<Path> walk = Files.walk(parent)) {
walk.filter(Files::isDirectory)
.forEach(dir -> {
if (!dirs.contains(dir)) {
dirs.add(dir);
}
});
} catch (IOException e) {
LOGGER.error("Error walking directories", e);
}
}
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Recursive directory explosion 🐞 Bug ➹ Performance

The AutoSetFileLinksUtil constructor now walks the database parent directory and adds every
subdirectory, which can be huge and redundant. This runs on the JavaFX/UI thread in the menu action
and can severely degrade performance when combined with recursive file searching.
Agent Prompt
### Issue description
`AutoSetFileLinksUtil` constructor currently walks the entire database parent tree and adds every subdirectory as a search root. This can be extremely slow and redundant, and in `AutoLinkFilesAction.execute` it happens on the JavaFX/UI thread.

### Issue Context
Existing `FileFinder` implementations already recurse within each configured directory root (e.g., `Files.find(..., Integer.MAX_VALUE, ...)`). Adding all subdirectories as additional roots multiplies traversal work.

### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[66-112]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java[52-76]
- jablib/src/main/java/org/jabref/logic/util/io/CitationKeyBasedFileFinder.java[74-92]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 168 to 191
for (LinkedFile existing : currentFiles) {

Optional<LinkedFile> replacement =
foundFiles.values().stream()
.filter(newFile ->
FileUtil.getBaseName(newFile.getLink())
.equals(FileUtil.getBaseName(existing.getLink())))
.findFirst();

if (replacement.isPresent()) {

LinkedFile newFile = replacement.get();

System.out.println("DEBUG: REPLACING FILE → " + existing.getLink());

updatedFiles.add(newFile);

updated = true;

} else {

updatedFiles.add(existing);

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Overwrites valid file links 🐞 Bug ✓ Correctness

Auto-link now replaces existing linked files purely by basename match, without checking whether the
existing link is broken or ensuring correct matching rules. This can overwrite a valid user-selected
link when another file with the same basename is found.
Agent Prompt
### Issue description
`doLinkAssociatedFiles` currently replaces existing linked files based solely on basename matching, without checking if the existing link is broken. This can overwrite correct user links and violates the intended broken-link repair behavior.

### Issue Context
The codebase contains explicit broken-link-only behavior (`BrokenLinkedFileNameBasedFileFinder`) and repair logic with extension matching (`autoLinkBrokenLinkedFiles`). Unit tests expect that copies do not trigger relinking.

### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[149-225]
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[234-258]
- jablib/src/main/java/org/jabref/logic/util/io/BrokenLinkedFileNameBasedFileFinder.java[59-64]
- jabgui/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java[633-660]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 363 to 387

String fileType = checkAndGetFileType(associatedFile);

// CRITICAL FIX: use RELATIVE TO DATABASE DIRECTORY ONLY
Path relativePath;

try {

Path baseDir = directories.get(0);

relativePath = baseDir.relativize(associatedFile);

} catch (Exception e) {

relativePath = associatedFile;

}

System.out.println("DEBUG RELATIVE PATH = " + relativePath);

return new LinkedFile(
"",
relativePath,
fileType
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Bad path relativization 🐞 Bug ✓ Correctness

Auto-linked files now compute relative paths using directories.get(0).relativize(...), which may
be unrelated to the found file’s actual base directory. This can produce incorrect relative paths or
fall back to absolute paths, harming portability and link resolution.
Agent Prompt
### Issue description
`buildLinkedFileFromPath` now relativizes against `directories.get(0)` which is not guaranteed to be the correct base directory. This can generate incorrect relative paths or absolute paths.

### Issue Context
`FileUtil.relativize` already implements correct selection of the base directory by checking prefixes (and real paths). `BibDatabaseContext.getFileDirectories` order can put user/library metadata directories first.

### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java[362-388]
- jablib/src/main/java/org/jabref/logic/util/io/FileUtil.java[287-317]
- jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java[147-196]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@github-actions github-actions bot added the status: changes-required Pull requests that are not yet complete label Feb 16, 2026
@github-actions
Copy link
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@shubh1978 shubh1978 force-pushed the fix/autolink-replace-broken-linkedfile branch from 2aad931 to 6ed9f7b Compare February 19, 2026 04:45
@jabref-machine
Copy link
Collaborator

Your pull request modified git submodules.

Please follow our FAQ on submodules to fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

first contrib status: changes-required Pull requests that are not yet complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Automatically set file links" doesn't work properly

2 participants