Fix notion-sync header crash on non-ASCII titles #48
1 changed files with 35 additions and 10 deletions
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Reference in a new issue