fix(nas): log swallowed filesystem errors instead of silently dropping them
nas-file-manager (21) and nas-financials-manager (9) had empty catch blocks that swallowed mkdir/write/rm/rename/stat/readdir failures with zero logging, making NAS issues undebuggable (violates the 'never silently swallow errors' rule). Added a contextual console.error to each real-failure catch (matching the existing service console.* pattern); control flow and return values unchanged. Left 3 ENOENT-as-expected catches (move/createFolder existence checks, symlink-traversal guard) as deliberate no-logs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -115,7 +115,12 @@ export class NasFileManager {
|
|||||||
return (
|
return (
|
||||||
fs.existsSync(this.basePath) && fs.statSync(this.basePath).isDirectory()
|
fs.existsSync(this.basePath) && fs.statSync(this.basePath).isDirectory()
|
||||||
);
|
);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] stat failed for basePath:",
|
||||||
|
this.basePath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +141,8 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
fs.mkdirSync(fullPath, { recursive: true, mode: 0o775 });
|
fs.mkdirSync(fullPath, { recursive: true, mode: 0o775 });
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] mkdir failed for path:", fullPath, err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +156,12 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
await fs.promises.rm(folderPath, { recursive: true, force: true });
|
await fs.promises.rm(folderPath, { recursive: true, force: true });
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] delete failed for path:",
|
||||||
|
folderPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +184,14 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
fs.renameSync(currentPath, newPath);
|
fs.renameSync(currentPath, newPath);
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] rename failed:",
|
||||||
|
currentPath,
|
||||||
|
"→",
|
||||||
|
newPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,14 +206,20 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
const stat = fs.lstatSync(dirPath);
|
const stat = fs.lstatSync(dirPath);
|
||||||
if (!stat.isDirectory()) return null;
|
if (!stat.isDirectory()) return null;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] lstat failed for path:", dirPath, err);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries: string[];
|
let entries: string[];
|
||||||
try {
|
try {
|
||||||
entries = fs.readdirSync(dirPath);
|
entries = fs.readdirSync(dirPath);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] readdir failed for path:",
|
||||||
|
dirPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +230,12 @@ export class NasFileManager {
|
|||||||
let lstat: fs.Stats;
|
let lstat: fs.Stats;
|
||||||
try {
|
try {
|
||||||
lstat = fs.lstatSync(fullPath);
|
lstat = fs.lstatSync(fullPath);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] lstat failed for entry:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +245,12 @@ export class NasFileManager {
|
|||||||
if (isLink) {
|
if (isLink) {
|
||||||
try {
|
try {
|
||||||
isDir = fs.statSync(fullPath).isDirectory();
|
isDir = fs.statSync(fullPath).isDirectory();
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] stat failed for symlink target:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
isDir = false;
|
isDir = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -237,8 +271,12 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
const target = fs.readlinkSync(fullPath);
|
const target = fs.readlinkSync(fullPath);
|
||||||
item.link_target = target;
|
item.link_target = target;
|
||||||
} catch {
|
} catch (err) {
|
||||||
// ignore
|
console.error(
|
||||||
|
"[nas-file-manager] readlink failed for:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +317,12 @@ export class NasFileManager {
|
|||||||
let realDirPath: string;
|
let realDirPath: string;
|
||||||
try {
|
try {
|
||||||
realDirPath = fs.realpathSync(dirPath);
|
realDirPath = fs.realpathSync(dirPath);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] realpath failed for path:",
|
||||||
|
dirPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
realDirPath = dirPath;
|
realDirPath = dirPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,14 +347,16 @@ export class NasFileManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.promises.mkdir(dirPath, { recursive: true, mode: 0o775 });
|
await fs.promises.mkdir(dirPath, { recursive: true, mode: 0o775 });
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] mkdir failed for path:", dirPath, err);
|
||||||
return "Cílová složka neexistuje";
|
return "Cílová složka neexistuje";
|
||||||
}
|
}
|
||||||
|
|
||||||
let stat: fs.Stats;
|
let stat: fs.Stats;
|
||||||
try {
|
try {
|
||||||
stat = await fs.promises.stat(dirPath);
|
stat = await fs.promises.stat(dirPath);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] stat failed for path:", dirPath, err);
|
||||||
return "Cílová složka neexistuje";
|
return "Cílová složka neexistuje";
|
||||||
}
|
}
|
||||||
if (!stat.isDirectory()) {
|
if (!stat.isDirectory()) {
|
||||||
@@ -376,7 +421,8 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
const stat = fs.lstatSync(fullPath);
|
const stat = fs.lstatSync(fullPath);
|
||||||
if (!stat.isFile()) return null;
|
if (!stat.isFile()) return null;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] lstat failed for path:", fullPath, err);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +459,8 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
const stat = await fs.promises.lstat(fullPath);
|
const stat = await fs.promises.lstat(fullPath);
|
||||||
isDir = stat.isDirectory();
|
isDir = stat.isDirectory();
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] lstat failed for path:", fullPath, err);
|
||||||
return "Soubor nebo složka neexistuje";
|
return "Soubor nebo složka neexistuje";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +470,12 @@ export class NasFileManager {
|
|||||||
} else {
|
} else {
|
||||||
await fs.promises.unlink(fullPath);
|
await fs.promises.unlink(fullPath);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] delete failed for path:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return isDir
|
return isDir
|
||||||
? "Nepodařilo se smazat složku"
|
? "Nepodařilo se smazat složku"
|
||||||
: "Nepodařilo se smazat soubor";
|
: "Nepodařilo se smazat soubor";
|
||||||
@@ -455,7 +507,12 @@ export class NasFileManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.promises.stat(fullFrom);
|
await fs.promises.stat(fullFrom);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] stat failed for source path:",
|
||||||
|
fullFrom,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return "Zdrojový soubor neexistuje";
|
return "Zdrojový soubor neexistuje";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +566,8 @@ export class NasFileManager {
|
|||||||
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
||||||
return "Nadřazená složka neexistuje";
|
return "Nadřazená složka neexistuje";
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] lstat failed for path:", dirPath, err);
|
||||||
return "Nadřazená složka neexistuje";
|
return "Nadřazená složka neexistuje";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +586,8 @@ export class NasFileManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.promises.mkdir(newPath, { mode: 0o775 });
|
await fs.promises.mkdir(newPath, { mode: 0o775 });
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error("[nas-file-manager] mkdir failed for path:", newPath, err);
|
||||||
return "Nepodařilo se vytvořit složku";
|
return "Nepodařilo se vytvořit složku";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +618,12 @@ export class NasFileManager {
|
|||||||
let entries: string[];
|
let entries: string[];
|
||||||
try {
|
try {
|
||||||
entries = fs.readdirSync(this.basePath);
|
entries = fs.readdirSync(this.basePath);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] readdir failed for basePath:",
|
||||||
|
this.basePath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,7 +635,12 @@ export class NasFileManager {
|
|||||||
if (fs.statSync(fullPath).isDirectory()) {
|
if (fs.statSync(fullPath).isDirectory()) {
|
||||||
return fullPath;
|
return fullPath;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] stat failed for entry:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -676,7 +745,12 @@ export class NasFileManager {
|
|||||||
try {
|
try {
|
||||||
const entries = fs.readdirSync(dirPath);
|
const entries = fs.readdirSync(dirPath);
|
||||||
return entries.length;
|
return entries.length;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-file-manager] readdir failed for path:",
|
||||||
|
dirPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
fs.mkdirSync(this.basePath, { recursive: true });
|
fs.mkdirSync(this.basePath, { recursive: true });
|
||||||
return fs.statSync(this.basePath).isDirectory();
|
return fs.statSync(this.basePath).isDirectory();
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] mkdir/stat failed for basePath:",
|
||||||
|
this.basePath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +49,12 @@ class NasFinancialsManager {
|
|||||||
const monthPath = path.join(yearPath, monthDir);
|
const monthPath = path.join(yearPath, monthDir);
|
||||||
try {
|
try {
|
||||||
if (!fs.statSync(monthPath).isDirectory()) continue;
|
if (!fs.statSync(monthPath).isDirectory()) continue;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] stat failed for monthPath:",
|
||||||
|
monthPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const filePath = path.join(monthPath, safeName);
|
const filePath = path.join(monthPath, safeName);
|
||||||
@@ -53,8 +63,12 @@ class NasFinancialsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (err) {
|
||||||
// best effort
|
console.error(
|
||||||
|
"[nas-financials-manager] cleanIssuedInvoice failed for:",
|
||||||
|
invoiceNumber,
|
||||||
|
err,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +87,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
fs.writeFileSync(fullPath, pdfBuffer);
|
fs.writeFileSync(fullPath, pdfBuffer);
|
||||||
return `${DIR_ISSUED}/${year}/${this.pad(month)}/${path.basename(fullPath)}`;
|
return `${DIR_ISSUED}/${year}/${this.pad(month)}/${path.basename(fullPath)}`;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] write failed for issued invoice:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +105,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
const data = fs.readFileSync(fullPath);
|
const data = fs.readFileSync(fullPath);
|
||||||
return { data, fileName: path.basename(fullPath) };
|
return { data, fileName: path.basename(fullPath) };
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] read failed for issued invoice:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +121,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
fs.unlinkSync(fullPath);
|
fs.unlinkSync(fullPath);
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] delete failed for issued invoice:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,7 +177,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
const data = fs.readFileSync(fullPath);
|
const data = fs.readFileSync(fullPath);
|
||||||
return { data, fileName: path.basename(fullPath) };
|
return { data, fileName: path.basename(fullPath) };
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] read failed for received invoice:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +194,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
fs.unlinkSync(fullPath);
|
fs.unlinkSync(fullPath);
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] delete failed for received invoice:",
|
||||||
|
fullPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,7 +220,12 @@ class NasFinancialsManager {
|
|||||||
try {
|
try {
|
||||||
fs.mkdirSync(dirPath, { recursive: true });
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
return dirPath;
|
return dirPath;
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
"[nas-financials-manager] mkdir failed for path:",
|
||||||
|
dirPath,
|
||||||
|
err,
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user