Fix notion-sync header crash on non-ASCII titles #48

Merged
amoussa1229 merged 1 commit from fix/notion-sync-metadata-encoding into main 2026-06-08 19:42:41 +00:00

View file

@ -44,6 +44,17 @@ function getPageTitle(page: Record<string, any>): string {
return page.id as string;
}
// S3 user-metadata values travel as HTTP headers, which must be US-ASCII with no
// control characters. Notion titles routinely contain em dashes and other
// non-ASCII characters (ERR_INVALID_CHAR otherwise). Strip to safe printable
// ASCII and cap at the 256-char metadata limit.
function sanitizeMetadataValue(value: string): string {
return value
.replace(/[^\x20-\x7E]/g, '') // drop non-printable / non-ASCII
.trim()
.slice(0, 256);
}
async function clearOldFiles(bucket: string): Promise<void> {
let continuationToken: string | undefined;
const toDelete: { Key: string }[] = [];
@ -128,7 +139,7 @@ export const handler = async (): Promise<void> => {
ContentType: 'text/markdown',
Metadata: {
'notion-page-id': pageId,
'notion-title': title.slice(0, 256), // S3 metadata value limit
'notion-title': sanitizeMetadataValue(title),
},
}),
);
@ -144,13 +155,27 @@ export const handler = async (): Promise<void> => {
console.log(`Upload complete. ${synced} synced, ${failed} failed.`);
console.log('Triggering Bedrock KB ingestion job...');
const ingestionRes = await bedrockAgent.send(
new StartIngestionJobCommand({
knowledgeBaseId: kbId,
dataSourceId: dsId,
}),
);
console.log(
`Ingestion job started: ${ingestionRes.ingestionJob?.ingestionJobId}`,
);
try {
const ingestionRes = await bedrockAgent.send(
new StartIngestionJobCommand({
knowledgeBaseId: kbId,
dataSourceId: dsId,
}),
);
console.log(
`Ingestion job started: ${ingestionRes.ingestionJob?.ingestionJobId}`,
);
} catch (err) {
// A ConflictException means an ingestion job is already running for this data
// source (e.g. an overlapping run). The freshly uploaded files will be picked
// up by that in-flight job, so this is benign — log and exit cleanly rather
// than failing the whole invocation.
if (err instanceof Error && err.name === 'ConflictException') {
console.log(
'Ingestion job already in progress; uploaded files will be picked up by the running job. Skipping.',
);
return;
}
throw err;
}
};