NickvisionApps/Parabolic · error · ArgumentException
The batch file is empty or is of invalid syntax.
Error message
The batch file is empty or is of invalid syntax.
What it means
GetForBatchFileAsync parses a batch file of URLs and throws ArgumentException when the parsed result is empty. This means the file either had no recognizable entries or its lines did not match the expected batch syntax. It is a fail-fast guard so downstream discovery is not run on nothing.
Solutions
- Open the batch file and confirm it is non-empty and each line contains a valid, supported URL in the expected syntax.
- Re-export/save the file in the exact batch format the parser expects (one URL per line, no stray HTML or CSV columns).
- Check the file encoding (save as UTF-8 without BOM) and remove blank/comment-only lines that may mask an empty parse.
- Verify the path argument points to the intended file, not an empty or mislabeled file.
- Catch ArgumentException and show the user which file failed to parse and why.
Example fix
// before
await discoveryService.GetForBatchFileAsync("downloads.txt"); // downloads.txt is empty
// after
var lines = File.ReadAllLines("downloads.txt")
.Where(l => !string.IsNullOrWhiteSpace(l) && Uri.IsWellFormedUriString(l.Trim(), UriKind.Absolute))
.ToList();
if (lines.Count == 0)
throw new InvalidOperationException("Batch file has no valid URLs.");
File.WriteAllLines("downloads.txt", lines);
await discoveryService.GetForBatchFileAsync("downloads.txt"); Defensive patterns
Strategy: validation
Validate before calling
var valid = File.Exists(path) &&
File.ReadAllLines(path).Any(l => !string.IsNullOrWhiteSpace(l) && Uri.IsWellFormedUriString(l.Trim(), UriKind.Absolute));
if (!valid) throw new InvalidOperationException("Batch file empty or unparsable"); Try / catch
try { await service.GetForBatchFileAsync(path); }
catch (ArgumentException ex) { /* report invalid/empty batch file to user */ } Prevention
- Pre-validate the batch file lines contain parseable absolute URLs before calling the API.
- Save batch files as plain UTF-8 without BOM in the exact expected one-URL-per-line syntax.
- Log the line count parsed so empty parses are caught early.
When it happens
Trigger: Calling GetForBatchFileAsync(path) where the file at path is empty, contains only comments/blank lines, or its lines do not match the parser's expected batch format (e.g. lines missing a parseable URL), causing ParseBatchFileAsync to return zero entries.
Common situations: Passing a file saved in the wrong format (HTML playlist page, CSV vs the expected syntax), a file with a BOM/encoding issue that breaks line parsing, pointing at a placeholder/zero-byte file, or using yt-dlp-style batch syntax the Parabolic parser does not accept.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of NickvisionApps/Parabolic@1118e6a3ab (2026-09-15).
Data as JSON: /api/errors/c4a4bfe8e265d2f6.
Report an issue: GitHub.
Appendix: source
Thrown at Nickvision.Parabolic.Shared/Services/DiscoveryService.cs:46
{
BatchFileDelimiter = '|';
}
public DiscoveryService(ILogger<DiscoveryService> logger, IConfigurationService configurationService, IThumbnailService thumbnailService, ITranslationService translationService, IYtdlpExecutableService ytdlpExecutableService)
{
_logger = logger;
_configurationService = configurationService;
_thumbnailService = thumbnailService;
_translationService = translationService;
_ytdlpExecutableService = ytdlpExecutableService;
}
public async Task<DiscoveryResult> GetForBatchFileAsync(string path, Credential? credential = null, CancellationToken cancellationToken = default)
{
var entries = await ParseBatchFileAsync(path, cancellationToken);
if (entries.Count == 0)
{
throw new ArgumentException("The batch file is empty or is of invalid syntax.");
}
var entryInfos = new List<DiscoveryResult>();
foreach (var entry in entries)
{
cancellationToken.ThrowIfCancellationRequested();
var urlInfo = await GetForUrlAsync(entry.Url, credential, entry.SuggestedSaveFolder, entry.SuggestedFilename, cancellationToken);
if (urlInfo is not null)
{
entryInfos.Add(urlInfo);
}
}
cancellationToken.ThrowIfCancellationRequested();
return new DiscoveryResult(new Uri(path), Path.GetFileNameWithoutExtension(path), entryInfos);
}
public Task<DiscoveryResult> GetForUrlAsync(Uri url, Credential? credential = null, CancellationToken cancellationToken = default) => GetForUrlAsync(url, credential, string.Empty, string.Empty, cancellationToken);
private async Task<DiscoveryResult> GetForUrlAsync(Uri url, Credential? credential, string suggestedSaveFolder, string suggestedFilename, CancellationToken cancellationToken = default)View on GitHub (pinned to 1118e6a3ab)