The same failure, twice, on workflows that share nothing
WF - Portfolio Video Publisher and WF-B Daily Portfolio Publisher are two different, independently-built n8n workflows that both happen to cross-post finished portfolio-project videos to Threads as part of a wider social push. One builds its caption from a Google Sheets row's threads_caption field; the other builds it inline in a Code node by concatenating a Groq-generated post_title and a separate threads body field with two newlines in between. Neither shares a node, a credential, or a caption-generation step. Both failed at the exact same HTTP call — POST https://graph.threads.net/v1.0/<user-id>/threads — with the identical n8n-level error text.
What n8n actually shows you
The execution log's headline error for both runs was NodeApiError: The service was not able to process your request, HTTP code 500. That message is n8n's generic fallback wording for this HTTP Request node whenever the upstream API returns a non-2xx status without n8n having a more specific mapped message for it. It's technically accurate and completely useless for diagnosis — it says nothing about which parameter, or why, or how to fix it. Looking only at that top line, both failures looked like a transient Threads outage, the same class of blip already covered by a separate article on this site about a Facebook video-fetch 500 that turned out to be Meta's side glitching, not a real bug.
The real error was one level down, not the top-level message
n8n's execution detail view keeps the actual upstream response body in the error's context.request and messages fields, not in the headline message shown in the workflow canvas. Opening that context on both executions showed the identical Threads API payload: {"error":{"message":"Param text must be at most 500 characters long.","type":"THApiException","code":100,"fbtrace_id":"..."}}. Threads' Graph API does document a 500-character cap on the text parameter for a media-container creation call — it just isn't anywhere in n8n's own node documentation for the generic HTTP Request node, since this node has no Threads-specific awareness at all; it's a plain authenticated HTTP call with a URL and query parameters.
Both real captions were built to look good as long-form social copy: a hook line, a body paragraph explaining the automation, a time-saved stat, hashtags, and in one case a bilingual English/Ukrainian pair separated by a divider. Reasonable for Facebook, LinkedIn, or Instagram — all of which tolerate captions well over 2,000 characters. Threads' own native app caption limit is much higher too (500 was actually Threads' original 2023 launch limit for the consumer app, since raised); the Graph API's text parameter for programmatic posts, however, still enforces the old 500-character ceiling regardless of what the app itself now allows a human to type.
Why this is easy to miss until it actually happens
Every other caption in both workflows' rotation had, by chance, stayed under 500 characters — short single-language captions, or ones without the bilingual pattern. The bug only surfaces on the specific captions long enough to cross the line, which is exactly the kind of intermittent-looking failure that gets mistaken for a flaky third-party API rather than a parameter validation rule that only some inputs happen to trip.
The fix
Truncate (or shorten at the caption-generation step, not after the fact) any Threads-bound text value to 500 characters before it reaches the HTTP Request node — a Code or Set node right before "Threads Create Media" that hard-caps the string length, ideally cutting on a word or sentence boundary rather than mid-word. Neither workflow had this cap; both do now. The generalizable habit: when an HTTP Request node to any platform API fails with a generic "service was not able to process your request" style message, check the execution's raw request/response context before assuming the platform itself is having problems — the specific rejection reason is almost always in there, just not in the headline.
A truncation that respects words and hashtags
Cutting at exactly 500 characters can leave half a word or a broken hashtag at the end. This Code node shortens the body and keeps the hashtags line intact:
const MAX = 500;
const body = String($json.threads_body || '').trim();
const tags = String($json.hashtags || '').trim();
const tail = tags ? '\n\n' + tags : '';
let room = MAX - tail.length;
let text = body;
if (text.length > room) {
text = text.slice(0, room - 1);
const cut = Math.max(text.lastIndexOf('. '), text.lastIndexOf(' '));
text = text.slice(0, cut > room * 0.6 ? cut : text.length).trim() + '…';
}
return [{ json: { ...$json, threads_text: (text + tail).slice(0, MAX) } }];
It prefers to cut at the end of a sentence, then at a space, and only falls back to a hard cut if neither is close to the limit. The final slice is a safety net, in case the hashtags line alone is very long.
Count what Threads counts
JavaScript's length counts UTF-16 code units, and most emoji count as two, some as more. If a caption is near the limit and full of emoji, the result can differ from what the platform counts. Leaving a margin of 10 to 20 characters is the simplest protection. A better fix than truncation is to ask the LLM for a Threads text of at most 400 characters in the first place, and keep truncation as the guard.
Other Threads errors that look the same in n8n
The headline "The service was not able to process your request" covers more than the length limit. Errors I have seen behind the same wrapper include a token that expired, a media URL Threads could not fetch, and publishing a video container before Threads had finished processing it. The fix for the last one is to poll the container's status until it says finished before calling the publish endpoint. In each case the real reason was in the error's details, not in the headline.
Frequently asked questions
What is the character limit for Threads posts via the API?
The text parameter for a media container accepted at most 500 characters in this case, even though the app allows longer posts.
Why does n8n only show 'The service was not able to process your request'?
That is n8n's generic message for a failed HTTP response. The Threads API's real error message is in the execution's error details.
How do I shorten a caption without cutting words?
Cut to the limit, then back to the last sentence end or space, and append the hashtags afterwards so they stay intact.
Do emoji count as more than one character?
In JavaScript most emoji count as two units, so leave a margin below 500 characters for captions with emoji.
n8n Automation Hub