{"record":{"id":"f05454d4d40b9e91","repo":"apache/beam","slug":"shard-number-pattern-s-not-found-in-shard-name-template-s","errorCode":null,"errorMessage":"Shard number pattern S+ not found in shard_name_template: %s","messagePattern":"Shard number pattern S\\+ not found in shard_name_template: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/filebasedsink.py","lineNumber":498,"sourceCode":"    if match:\n      shard_name_template = shard_name_template.replace(\n          match.group(0), '%%(uuid)0%dd' % len(match.group(0)))\n    return shard_name_template\n\n  @staticmethod\n  def _template_replace_num_shards(shard_name_template):\n    match = re.search('N+', shard_name_template)\n    if match:\n      shard_name_template = shard_name_template.replace(\n          match.group(0), '%%(num_shards)0%dd' % len(match.group(0)))\n    return shard_name_template\n\n  @staticmethod\n  def _template_replace_shard_num(shard_name_template):\n    match = re.search('S+', shard_name_template)\n    if match is None:\n      # shard name is required in the template.\n      raise ValueError(\n          \"Shard number pattern S+ not found in shard_name_template: %s\" %\n          shard_name_template)\n    return shard_name_template.replace(\n        match.group(0), '%%(shard_num)0%dd' % len(match.group(0)))\n\n  @staticmethod\n  def _template_to_format(shard_name_template):\n    if not shard_name_template:\n      return ''\n    # shard_num is required in the template, while others are optional.\n    replace_funcs = [\n        FileBasedSink._template_replace_shard_num,\n        FileBasedSink._template_replace_num_shards,\n        FileBasedSink._template_replace_uuid,\n        FileBasedSink._template_replace_window\n    ]\n    for func in replace_funcs:\n      shard_name_template = func(shard_name_template)","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/filebasedsink.py#L480-L516","documentation":"FileBasedSink._template_replace_shard_num rewrites the S+ pattern in a shard name template into a numeric format specifier; if the template contains no 'S' sequence, a ValueError is raised because a shard number placeholder is mandatory.","triggerScenarios":"Passing a shard_name_template such as '-of-N' or 'part-' without any 'S' characters (e.g. shard_name_template='') to a sink or to _template_replace_shard_num directly.","commonSituations":"Custom shard templates edited to remove the S token; templates copied from systems using different placeholders.","solutions":["Include an S pattern in the template, e.g. '-SSSS-of-NNNN'","Use the default shard template (DEFAULT_SHARD_NAME_TEMPLATE)","Pass shard_name_template=None to get default behavior instead of an S-less string"],"exampleFix":"// before\nWriteToText('/out/data', shard_name_template='-of-NN')\n// after\nWriteToText('/out/data', shard_name_template='-SSS-of-NN')","handlingStrategy":"validation","validationCode":"import re\nif shard_name_template and not re.search('S+', shard_name_template):\n    raise ValueError(f'shard_name_template must contain an S+ pattern: {shard_name_template!r}')","typeGuard":"def has_shard_pattern(t: str) -> bool:\n    return re.search(r'S+', t) is not None","tryCatchPattern":null,"preventionTips":["Keep the S token in custom shard templates (e.g. -SSS-of-NN)","Use shard_name_template=None for defaults","Lint sink options for the S pattern before job submission"],"tags":["python","apache-beam","io","shard-template","format"],"backgroundTag":"invalid-argument-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}